Screen Space Decals
in Warhammer 40,000: Space Marine


                              Pope Kim
                    Senior 3D Programmer
                  Square Enix / Eidos Montreal
                  Relic Entertainment / THQ Canada (past)
작년 KGC 발표 이후….

 스페이스마린의 렌더링 기법
  데니엘 박사님과 2시간 공동발표
작년 KGC 발표 이후….

 그 후, 포프는 꽃미남 프로그래머로 널리 명성을…
작년 KGC 발표 이후….

 하지만 같이 발표했던 데니엘 박사님은 포프의 외모에
 밀려 소리소문없이…. -_-
 사랑하는 동료로서 마음이
 아파서 데니엘 박사님의
 간지나는 참 모습을 다음
 장에 공개…
데니엘 박사님의 참모습…(?)
작년 KGC 발표 이후….

 여기까진 농담… (잠좀 깨셨죠? -_-)
 스페이스마린의 렌더링 기법 - 2시간짜리
 슬라이드
  129장 = 1분에 한장하기에도 벅찼….
  http://kblog.popekim.com/2011/11/blog-post.html
 말도 엄청나게 빨리 해야했음
  증거 동영상:
   http://www.kocca.kr/knowledge/seminar/1775011_3306.html
  (이라고 했지만 사실은 원래 말을 빨리 함 -_-)
하지만 생각외로 국내외로 엄청난 반응
국내외 개발자들의 추가발표 요청 내용 2개

 렐릭의 파티클 시스템
  데니엘 박사님의 KGC 2012 발표
  “모두가서 보세요!” 라고 하고 싶지만 어제 이미 발표 -_-
 그리고 스크린 스페이스 데칼
  이미 발표자 본인이 Siggraph 2012에서 발표했음
  지금 KGC 2012에서 발표하는 것도 시그래프 발표에 기반
 그리고 올해는 좀더 여유롭게 발표
  시간도 1시간 뿐
  슬라이드 수도 112장 밖(?)에 안됩니다…..
올해는 시간이 좀 여유로우니 발표자 소개도…

 이름: Pope Kim (김포프)
 경력(시니어 3D 프로그래머)
   스퀘어 에닉스(아이도스)
    몬트리올 (2012 - )
   렐릭 (THQ) (2008 - 2012)
   캡콤 밴쿠버 (2006 - 2008)
   기타 등등
잘난척   여태까지 출시한 게임들…
계속 잘난척 발표자 소개

 학력:
   연세대 법대 졸
   BCIT 컴공 수석졸업
 기타 등등
     밴쿠버 예술대학 셰이더 프로그래밍 강사 (2007 - 2009)
     시그래프 2012 강연
     KGC 2011 강연
     게임개발포에버(www.gamedevforever.com) 운영자(?)
은퇴계획   발표자 소개…
그럼 이제 본격적으로 데칼에 대해…

 알아보기 전에 스페이스마린을 모르시는 분들을 위해
 비디오 한편…

 (작년과 같은 비디오지만… -_-)
그럼 정말 데칼에 대해

 알아보고 싶지만…
 디퍼드 라이팅에 대해 잠시 소개부터…
 그래야만 이해가 되요~
포워드 렌더링

 보통 알고 있는 메쉬를 그리는
 방법
 메쉬 하나를 그리면서 모든
 계산을 한번에
  조명
  텍스처 등등


                     Dawn of War 2, Relic Entertainment
포워드 렌더링

 문제점
  많은 조명을 허용하면 성능저하
  조명수를 제한하면 품질저하
  다음과 같은 건 거의 불가능




                      출처: Light Pre-Pass 2009, Wolfgang Engel
디퍼드 기법들

 조명과 메쉬의 분리!
 디퍼드 렌더링 또는 디퍼드 라이팅
  개념상의 큰 차이는 없음
  미묘한 구현상의 차이
  스페이스마린은 디퍼드 라이팅
 디퍼드 = 다단계, 포워드 = 한단계로 이해
디퍼드 라이팅

 디퍼드 라이팅으로 최종결과를 이렇게 그리려면
디퍼드 라이팅

 Step 1:
    메쉬의 속성들을
    화면공간안에 저장
    속성:
       법선
       Spec Power
    결과: Gbuffer 텍스처
    (2D)
디퍼드 라이팅

 Step 2:
    Gbuffer를 이용하여 그
    위에 조명을 그림
    결과: 조명결과 텍스처
    (2D)
디퍼드 라이팅

 Step 3:
    메쉬를 다시한번
    그리면서 디퓨즈 텍스처
    등에 조명결과를 적용
    결과: 최종화면
디퍼드 기법을 자세히 배우고 싶으시다면…

 오늘 이창희님의 강의를 들으세요
  제 강의 끝나고 그냥 여기 앉아계시면 됩니다~
SSD 이전의 데칼기법?
SSD 이전의 데칼기법?

 2008~2009년 어느날, 스페이스마린에 사용할 데칼
 시스템을 만들라는 명령을 받음
 난생 처음 해보는 일
 따라서 리서치를 먼저 해보니…

 총알을 벽에 쐈을 때 데칼을 어떻게 그리곤 했는지
 간단히 5분간 알아보자
버텍스 4개로 만든 벽
여기에 총알을 쏘면
이렇게 흠집을 보여주는 텍스처를 그려야함
말은 쉽지만… 정작 어떻게?

 충돌 지점에 이 텍스처를 그리고 싶음


 근데 텍스처를 그리려면 메쉬를 그려야만 함
 그럼 대충 사각형 메쉬에 텍스처를 씌워서 그리면 되겠군
 근데 벽면 위에 착~ 달라붙는 메쉬를 어떻게 만들지?
흠집 텍스처를 포함하는 가장 작은 patch를 찾자
이제 그 patch를 복제(duplicate)
이제 간단히 텍스처를 씌워서 그림
일반적으로 사용했던 해결법

1. (진짜 쉬움) 벽 메쉬의 폴리곤 수를 늘림
2. (그닥 안 쉬움) 복제한 메쉬패치에 있는 정점마다 UV
  좌표를 잘~ 계산해줌
1. 폴리곤 수를 늘리는 방법
2. UV를 잘~ 계산하는 법


   (-4.5, -3.2)                     (3.4, -3.2)

                  (0, 0)


                           (1, 1)
    (-4.5, 4)
                                     (3.4, 4)
하지만 여전히 문제가…

1. 폴리곤 수를 늘리면 정점수가 늘어나니…
 –    정점들을 훑는데(iterate) 시간이 더 걸림
 –    메모리 사용량 증가 (콘솔에서 특히 치명적… 512MB 들어는 봤나
      -_-)
2. 쓸데없이 래스터라이제이션 하는 픽셀이 늘어나니
     성능저하
 –    텍스처 가장자리(edge)가 완전투명해야함
 –    메쉬가 복잡하면 UV 계산이 너무 어려움
UV 계산이 안쉽다니까…..

 이렇게 복잡한 석상
 메쉬가 있으면 대체
 UV는 어떻게
 계산하라고…
그래도 난 천재니까?....

 그래서 이 모든 문제들을 해결하려고 Screen Space
 Decal이란 기막힌 기법을 만들어 냈겠죠?
그래도 난 천재니까?....

 그래서 이 모든 문제들을 해결하려고 Screen Space
 Decal이란 기막힌 기법을 만들어 냈겠죠?


          그.럴.리.가….
난 천재니까?....

 그래서 이 모든 문제들을 해결하려고 Screen Space
 Decal이란 기막힌 기법을 만들어 냈겠죠?


              그.럴.리.가….


 사실 이전 방법이 만들기 너무 복잡해보여서….
 하지만 SSD가 저 문제들을 해결한건 사실..^_^
스크린 스페이스 데칼 (SSD)

 지난 1~2년간 다른 개발자들이 비슷한 기법을 소개했음
  Deferred Decals (Jan Krassnigg, 2010)
  Volume Decals (Emil Persson, 2011)
 SSD는 그 전에 개발했으나 실제 알고리듬은 매우 비슷함.
 (이름이 좀더 멋질뿐…. -_-)
 따라서 알고리듬을 가볍게 살펴본 뒤
 스페이스마린에서 SSD를 사용한 방법과 발견한
 문제점들, 그리고 그 해결책에 더욱 초점을 둘것임
스페이스마린에서 SSD를 쓴 곳들

 파티클 효과(FX)에 국한하지 않음
 말 그대로 화면의 절반이 SSD:
     벽에 끈적하게 들러붙은 핏자국
     벽에 조각한 석상
     콘크리트 바닥이 탄 자국
     오크들이 벽에 페인트로 낙서질 해 놓은것
     바닥에 쌓여있는 돌더미들
     총알구멍
     폭발자국
     ......기타 등등등
 특히 배경 아티스트들이 너무너무 좋아했어요~~~
This slide has a 16:9 media window
                             SSD ON
This slide has a 16:9 media window
                             SSD OFF
구현 디테일

1.   SSD를 제외한 메쉬들을 화면에 그림
2.   SSD 상자를 그림(rasterization)
3.   각 픽셀마다 장면깊이(scene depth)를 읽어옴
4.   그 깊이로부터 3D 위치를 계산함
5.   그 3D 위치가 SSD 상자 밖이면 레젝션(rejection)
6.   그렇지 않으면 데칼 텍스처를 그림
This slide has장면에서..
            이 a 16:9 media window
이 데칼을 그려보죠
This slide has a 16:9 media window
This SSD를 제외한 메쉬들을 그림
  1. slide has a 16:9 media window
This slide SSDa상자를 그림 window
        2. has 16:9 media
This slide SSDa상자를 그림 window
        2. has 16:9 media


     하지만 이건 뭔가
     아니잖아????

     이걸 프로젝터처럼
     사용하고 싶음
This slide has a장면깊이를 읽어옴
 3. 각 픽셀마다 16:9 media window
4. 그 깊이로부터 3D위치를 계산

float2 screenPosition = clipPosition.xy / clipPosition.w;

float2 depth_uv = screenPosition * float2(0.5f, -0.5f)
                 + float2(0.5f, 0.5f);
depth_uv += ScreenDimension.zw;          Half-pixel Offset Basically
float sceneDepth = tex2D(DepthMap, depth_uv).r;

float4 scenePosView = float4(clipPosition.xy * sceneDepth
         / (Deproject.xy * clipPosition.w), -depth, 1);

                            Deproject.X = ProjectionMatrix.M11;
                            Deproject.Y = ProjectionMatrix.M22;
This 5. SSD 상자밖이면, 리젝션
     slide has a 16:9 media window
                            밖
              안



밖
5. SSD 상자밖이면 리젝션

• 간단히 뷰공간의 위치를 SSD 상자의 물체공간으로 변환
• 위치가 0.5 보다 큰 픽셀은 상자 밖에 있는 것



position = mul(scenePosView, InvWorldView);
clip(0.5f - abs(position.xyz));
This 6. 상자안이면 데칼을 그림
     slide has a 16:9 media window




            // 데칼 텍스처의 UV
            float2 uv = position.xz;
            uv += 0.5f;
그럼 조명은 거저먹음…
This slide has a 16:9 media window




                   Without SSD
그럼 조명은 거저먹음…
This slide has a 16:9 media window




                   With SSD
컴바이너 패스는 16:9 media window
This slide has a 그냥 동일과정 반복
컴바이너 패스는 16:9 media window
This slide has a 그냥 동일과정 반복
컴바이너 패스는 16:9 media window
This slide has a 그냥 동일과정 반복
Mix-n-Match

 아티스트는 Gbuffer 또는 컴바이너 패스에 그려지지 않는
  데칼을 만들수 있음
 디퍼드 라이팅 엔진을 쓰기에 역시 공짜로 얻은 혜택
This slide has a+ Combinerwindow
       Gbuffer 16:9 media
Gbuffer만
This slide has a 16:9 media window
Combiner 패스만
This slide has a 16:9 media window
실제게임속 예제(둘다)
실제게임속 예제 (둘다)
실제 게임속 예제 (GBuffer)
실제 계임속 예제 (GBuffer)
실제 계임속 예제 (Combiner)
실제 게임속 예제 (Combiner)
아티스트에게 자유를….

 아티스트는 *.ssdecal
 파일을 만듬 (사실 그냥
 XML 파일)
 레벨 에디터에서,
 SSD를 끌어다 놓음
 이제부터 WYSIWYG.
 각 인스턴스별로 수정도
 가능
문제점들 & 우리의 해결책

1.   알파 블렌딩
2.   움직이는 물체들
3.   옆면이 늘어나요…. ㅜ.ㅜ
4.   짤린(clipped) 데칼
5.   성능
1. 알파블렌딩 (법선)

• 컴바이너 패스에서 투명한 물체를 그리는 건 큰 문제없음
• 법선(normal)을 혼합 해야하는 Gbuffer가 문제
  – 첫 구현: 알파테스트 사용
  – 거의 마지막 구현: Crytek의 Best Fit Normal 기법 + 알파블렌딩
  – 하지만 3 개월 뒤, 우리가 Best Fit Normal을 구현한 코드에서 버그
   발견. 이전에 쓰던 법선저장법과 동일했음.. -_-
  – 그래도 법선 블렌딩이 이상하다고 불평하는 아티스트가 없었으니
   시각적으로 문제가 없는 것… 그래서 그냥 그대로 뒀음…
  – 수학적으론 틀림… 하지만 게임개발에선 아티스트가 왕. 그러니
   틀리든가 말던가…. (올해도 디스 당할지도…. -_-)
1. 알파블렌딩(Spec Power)

• Gbuffer의 알파채널에 Specular Power를 저장


• 일반적인 알파블렌딩 사용불가
  – SSD 셰이더의 알파 출력(output)값은 RGB(법선) 혼합에 사용
  – 해결책: Blend Factor!

     AlphaBlendFunction      =   BlendFunction.Add;
     AlphaSourceBlend        =   Blend.BlendFactor;
     AlphaDestinationBlend   =   Blend.InverseSourceAlpha;
     BlendFactor             =   ssd.SpecularPower / 255.0f;
1. 알파 블렌딩(Spec Power)
This slide has a 16:9 media window
1. 알파블렌딩(Spec Power)
This slide has a 16:9 media window




                   Power = 128
1. 알파블렌딩(Spec Power)
This slide has a 16:9 media window

            Power = 40




                   Power = 128
This slide has a 16:9물체들 window
         2. 움직이는 media
This slide has a 16:9물체들 window
         2. 움직이는 media
2. 움직이는 물체들

• 움직이는 물체에 데칼을 붙여버릴 수도 있었음
• 하지만 스키닝 입힌 메쉬(예: 오크의 팔)은 여전히 문제
• 그래서 그냥 움직이는 물체에는 데칼을 그냥 안
 적용했음… -_-
• 초간단 스텐실 버퍼 기법으로 해결
Stencil
This slide has a 16:9 media window
This slide has a 16:9물체들 window
         2. 움직이는 media
This3. 옆면이 늘어나요… ㅜ.ㅠ
     slide has a 16:9 media window
3. 옆면이 늘어나요… ㅜ.ㅠ

• SSD 상자의 투영면이 완전히 충돌하는 메쉬안에
 들어가지 않을 때 발생하는 문제
• 처음발견한 문제, 여러가지 시도를 한 문제
• 하지만 데칼상자의 투영방향과 Gbuffer의 법선방향이
 이루는 각이 어느정도 커지면 그냥 단순히 리젝션
This3. 옆면이 늘어나요… ㅜ.ㅠ
     slide has a 16:9 media window

                           90 도
3. 옆면이 늘어나요… ㅜ.ㅠ

 아티스트가 지정한 각도
 이상이면 무조건 픽셀
 리젝션
 180도로 지정하면 전혀
 리젝션을 안함
 대충 60도로 지정하는게
 최고더라구요….?
3. 옆면이 늘어나요… ㅜ.ㅠ

1. 정점 셰이더에서 데칼상자의 방위를 구함:

   output.Orientation = normalize(WorldView[1].xyz);


2. gNormalThreashold은 cos(각도)
3. 픽셀 셰이더에서 Gbuffer 법선을 읽어와 리젝션 테스트
   float3 normal = DecodeGBufferNormal( tex2D(
               GNormalMap, depth_uv ) );
   clip(dot(normal, orientation) - gNormalThreshold);
3. 옆면이 늘어나요… ㅜ.ㅠ

• 단순 리젝션 외에 우리가 시도해본 방법들
 – 데칼상자의 방위와 정점법선이 이루는 각이 커짐에 따라 데칼이
   서서히 사라지게 함: 둥근 파이프등에서 정말 안이쁨 -_-
 – 데칼상자의 방위와 Gbuffer 법선이 이루는 각이 커짐에 따라
   데칼이 서서히 사라지게 함
   • 이미 만들어놓은 데칼 텍스처들을 너무 흐리게 만들었음
   • 노이즈가 많이 낀 gbuffer에서 아티스트들이 단순 리젝션을 더 선호했음
   • 처음부터 이 방법을 썼으면 썼을지도… 여러분 게임에서 시도해 볼만한 가치는 있음
4. 짤린(clipped) 데칼

• 배경아트 데칼에서는 별로 문제가 아님
  – 이미 배경 아티스트들이 성능상의 이유로 얇은(thin) 데칼을 사용
• 파티클에서 큰 폭발이 일어날때 종종 발생하는 문제
  – 카메라가 데칼상자 안에 들어가면
  – 픽셀이 래스터라이제이션 조차 안되서 생기는 문제
This slide has a 데칼 media window
         4. 짤린 16:9 (OK)
This slide has a 데칼 media window
         4. 짤린 16:9 (OK)
4. Clipped Decal (BAD)
This slide has a 16:9 media window
4. Clipped Decal (BAD)
This slide has a 16:9 media window
4. 짤린 데칼(해결책)

• 카메라와 데칼이 충돌하면
• 뒷면(backface)을 대신 그림. 하지만 깊이 테스트 방향을
 뒤집어야 함
• 하.지.만… 성능이… 마구 떨어져요….
  – 깊이 테스트를 뒤집으면 계층적 깊이(Hi-Z)또 꺼져요.. ㅜ.ㅠ
  – 하지만 파티클 데칼에서만 문제가 되고, 이것에 대한 상상도못할
   엄청난 해결책꼼수가 있음 (뒤를 보세요)
This 4. 짤린 데칼16:9 media window
     slide has a (뒷면 그리기)
This 4. 짤린 데칼16:9 media window
     slide has a (뒷면 그리기)
5. 성능

• 어차피 리젝션할 픽셀이라면 래스터라이제이션 조차
 안하는게 좋음
• 깊이 테스트 방향을 뒤집어서 Hi-Z도 끄는걸 피해야 함
• 간단히 말해 데칼을 매우 얇게 만들 것
  – 배경아트 데칼은 매우 쉽게 해결가능 = 노가다.... -_-
  – 파티클 데칼들은 노가다가 거의 불가능…
• 이런 방침을 따른 스페이스마린은 파티클 데칼이 완전히
 미쳐 날뛰지 않는한 언제나 30+ FPS로 실행 ^_^
a 성능
  This slide has5. 16:9 media window




이 데칼을 그리는 두가지 방법
a 성능
  This slide has5. 16:9 media window




엄청 두껍게
a 성능
  This slide has5. 16:9 media window




아니면 얇게
a 성능
  This slide has5. 16:9 media window




픽셀셰이더를 이만큼 낭비
a 성능
This slide has5. 16:9 media window
            폭발물을 투척하는 오크가 많음
a 성능
This slide has5. 16:9 media window
            그럼 이따만한 데칼들이 뒤에 남음
a 성능
This slide has5. 16:9 media window
            그럼 이따만한 데칼들이 뒤에 남음

                   때론 이놈들 5개가 차곡차곡
                   겹치기도…
a 성능
This slide has5. 16:9 media window
            그럼 이따만한 데칼들이 뒤에 남음

                   때론 이놈들 5개가 차곡차곡
                   겹치기도…

                   5 fullscreen 패스와 맞먹음 =
                   스페이스마린이 25 FPS까지
                   떨어지는 유일한 때

                   우리의 해결책? 꼼수?
a 성능
This slide has5. 16:9 media window
                         이것!
a 성능
This slide has5. 16:9 media window
                         이것!

                        오버레이로 숨겨요!
                        파티클로 발라요!
a 성능
This slide has5. 16:9 media window
                         이것!

                        오버레이로 숨겨요!
                        파티클로 발라요!

                    느려져도 눈치 못채는게 함정!
a 성능
This slide has5. 16:9 media window
                         이것!

                        오버레이로 숨겨요!
                        파티클로 발라요!

                    느려져도 눈치 못채는게 함정!


                       사실 이럴려고 한 건
                       아닌데…
                       덕분에 할일이 줄었..
Special Thanks

• 더이상 자기 직원이 아닌데도 발표를 허락해준 Relic
• 스페이스마린 렌더링 프로그래머들
• 아름다운 아트를 만들고, 렌더링 프로그래머를 맨날
  괴롭혀준 아티스트들!
More Special Thanks

• 온갖 탄압을 받으면서도 꿋꿋이 게임을 만드시는 한국
  현직 게임개발자분들과 지망생분들…
• 게임개발포에버 필자분들
참조문헌

• ENGEL, W. 2009, Designing a Renderer for Multiple Lights –
  The Light Pre-Pass Renderer. In ShaderX7: Advanced
  Rendering Techniques, Charles River Media
• KAPLANYAN A. 2010, CryEngine 3: Reaching the Speed of
  Light, Siggraph 2011
• KRASSNIGG, J. 2010. A Deferred Decal Rendering
  Technique. In Game Engine Gems 1, Jones and Barlett
• PERSSON, E. 2011. Volume Decal. In GPU Pro 2, A K Peters
질문이 있으시다면 사진처럼 친절하게 답해 드려요~

• 스페이스마린 렌더링 엔진 발표자료(KGC 2011) :
  http://kblog.popekim.com/2011/11/blog-post.html

• Twitter:@BlindRendererKR (한글)
         @BlindRenderer(English)
• E-mail: blindrenderer@gmail.com

스크린 스페이스 데칼에 대해 자세히 알아보자(워햄머 40,000: 스페이스 마린)

  • 1.
    Screen Space Decals inWarhammer 40,000: Space Marine Pope Kim Senior 3D Programmer Square Enix / Eidos Montreal Relic Entertainment / THQ Canada (past)
  • 2.
    작년 KGC 발표이후….  스페이스마린의 렌더링 기법  데니엘 박사님과 2시간 공동발표
  • 3.
    작년 KGC 발표이후….  그 후, 포프는 꽃미남 프로그래머로 널리 명성을…
  • 4.
    작년 KGC 발표이후….  하지만 같이 발표했던 데니엘 박사님은 포프의 외모에 밀려 소리소문없이…. -_-  사랑하는 동료로서 마음이 아파서 데니엘 박사님의 간지나는 참 모습을 다음 장에 공개…
  • 5.
  • 6.
    작년 KGC 발표이후….  여기까진 농담… (잠좀 깨셨죠? -_-)  스페이스마린의 렌더링 기법 - 2시간짜리  슬라이드  129장 = 1분에 한장하기에도 벅찼….  http://kblog.popekim.com/2011/11/blog-post.html  말도 엄청나게 빨리 해야했음  증거 동영상: http://www.kocca.kr/knowledge/seminar/1775011_3306.html  (이라고 했지만 사실은 원래 말을 빨리 함 -_-)
  • 7.
  • 8.
    국내외 개발자들의 추가발표요청 내용 2개  렐릭의 파티클 시스템  데니엘 박사님의 KGC 2012 발표  “모두가서 보세요!” 라고 하고 싶지만 어제 이미 발표 -_-  그리고 스크린 스페이스 데칼  이미 발표자 본인이 Siggraph 2012에서 발표했음  지금 KGC 2012에서 발표하는 것도 시그래프 발표에 기반  그리고 올해는 좀더 여유롭게 발표  시간도 1시간 뿐  슬라이드 수도 112장 밖(?)에 안됩니다…..
  • 9.
    올해는 시간이 좀여유로우니 발표자 소개도…  이름: Pope Kim (김포프)  경력(시니어 3D 프로그래머)  스퀘어 에닉스(아이도스) 몬트리올 (2012 - )  렐릭 (THQ) (2008 - 2012)  캡콤 밴쿠버 (2006 - 2008)  기타 등등
  • 10.
    잘난척 여태까지 출시한 게임들…
  • 11.
    계속 잘난척 발표자소개  학력:  연세대 법대 졸  BCIT 컴공 수석졸업  기타 등등  밴쿠버 예술대학 셰이더 프로그래밍 강사 (2007 - 2009)  시그래프 2012 강연  KGC 2011 강연  게임개발포에버(www.gamedevforever.com) 운영자(?)
  • 12.
    은퇴계획 발표자 소개…
  • 13.
    그럼 이제 본격적으로데칼에 대해…  알아보기 전에 스페이스마린을 모르시는 분들을 위해 비디오 한편… (작년과 같은 비디오지만… -_-)
  • 14.
    그럼 정말 데칼에대해  알아보고 싶지만…  디퍼드 라이팅에 대해 잠시 소개부터…  그래야만 이해가 되요~
  • 15.
    포워드 렌더링  보통알고 있는 메쉬를 그리는 방법  메쉬 하나를 그리면서 모든 계산을 한번에  조명  텍스처 등등 Dawn of War 2, Relic Entertainment
  • 16.
    포워드 렌더링  문제점  많은 조명을 허용하면 성능저하  조명수를 제한하면 품질저하  다음과 같은 건 거의 불가능 출처: Light Pre-Pass 2009, Wolfgang Engel
  • 17.
    디퍼드 기법들  조명과메쉬의 분리!  디퍼드 렌더링 또는 디퍼드 라이팅  개념상의 큰 차이는 없음  미묘한 구현상의 차이  스페이스마린은 디퍼드 라이팅  디퍼드 = 다단계, 포워드 = 한단계로 이해
  • 18.
    디퍼드 라이팅  디퍼드라이팅으로 최종결과를 이렇게 그리려면
  • 19.
    디퍼드 라이팅  Step1:  메쉬의 속성들을 화면공간안에 저장  속성:  법선  Spec Power  결과: Gbuffer 텍스처 (2D)
  • 20.
    디퍼드 라이팅  Step2:  Gbuffer를 이용하여 그 위에 조명을 그림  결과: 조명결과 텍스처 (2D)
  • 21.
    디퍼드 라이팅  Step3:  메쉬를 다시한번 그리면서 디퓨즈 텍스처 등에 조명결과를 적용  결과: 최종화면
  • 22.
    디퍼드 기법을 자세히배우고 싶으시다면…  오늘 이창희님의 강의를 들으세요  제 강의 끝나고 그냥 여기 앉아계시면 됩니다~
  • 23.
  • 24.
    SSD 이전의 데칼기법? 2008~2009년 어느날, 스페이스마린에 사용할 데칼 시스템을 만들라는 명령을 받음  난생 처음 해보는 일  따라서 리서치를 먼저 해보니…  총알을 벽에 쐈을 때 데칼을 어떻게 그리곤 했는지 간단히 5분간 알아보자
  • 25.
  • 26.
  • 27.
    이렇게 흠집을 보여주는텍스처를 그려야함
  • 28.
    말은 쉽지만… 정작어떻게?  충돌 지점에 이 텍스처를 그리고 싶음  근데 텍스처를 그리려면 메쉬를 그려야만 함  그럼 대충 사각형 메쉬에 텍스처를 씌워서 그리면 되겠군  근데 벽면 위에 착~ 달라붙는 메쉬를 어떻게 만들지?
  • 29.
    흠집 텍스처를 포함하는가장 작은 patch를 찾자
  • 30.
    이제 그 patch를복제(duplicate)
  • 31.
  • 32.
    일반적으로 사용했던 해결법 1.(진짜 쉬움) 벽 메쉬의 폴리곤 수를 늘림 2. (그닥 안 쉬움) 복제한 메쉬패치에 있는 정점마다 UV 좌표를 잘~ 계산해줌
  • 33.
    1. 폴리곤 수를늘리는 방법
  • 34.
    2. UV를 잘~계산하는 법 (-4.5, -3.2) (3.4, -3.2) (0, 0) (1, 1) (-4.5, 4) (3.4, 4)
  • 35.
    하지만 여전히 문제가… 1.폴리곤 수를 늘리면 정점수가 늘어나니… – 정점들을 훑는데(iterate) 시간이 더 걸림 – 메모리 사용량 증가 (콘솔에서 특히 치명적… 512MB 들어는 봤나 -_-) 2. 쓸데없이 래스터라이제이션 하는 픽셀이 늘어나니 성능저하 – 텍스처 가장자리(edge)가 완전투명해야함 – 메쉬가 복잡하면 UV 계산이 너무 어려움
  • 36.
    UV 계산이 안쉽다니까….. 이렇게 복잡한 석상 메쉬가 있으면 대체 UV는 어떻게 계산하라고…
  • 37.
    그래도 난 천재니까?.... 그래서 이 모든 문제들을 해결하려고 Screen Space Decal이란 기막힌 기법을 만들어 냈겠죠?
  • 38.
    그래도 난 천재니까?.... 그래서 이 모든 문제들을 해결하려고 Screen Space Decal이란 기막힌 기법을 만들어 냈겠죠? 그.럴.리.가….
  • 39.
    난 천재니까?....  그래서이 모든 문제들을 해결하려고 Screen Space Decal이란 기막힌 기법을 만들어 냈겠죠? 그.럴.리.가….  사실 이전 방법이 만들기 너무 복잡해보여서….  하지만 SSD가 저 문제들을 해결한건 사실..^_^
  • 40.
    스크린 스페이스 데칼(SSD)  지난 1~2년간 다른 개발자들이 비슷한 기법을 소개했음  Deferred Decals (Jan Krassnigg, 2010)  Volume Decals (Emil Persson, 2011)  SSD는 그 전에 개발했으나 실제 알고리듬은 매우 비슷함. (이름이 좀더 멋질뿐…. -_-)  따라서 알고리듬을 가볍게 살펴본 뒤  스페이스마린에서 SSD를 사용한 방법과 발견한 문제점들, 그리고 그 해결책에 더욱 초점을 둘것임
  • 41.
    스페이스마린에서 SSD를 쓴곳들  파티클 효과(FX)에 국한하지 않음  말 그대로 화면의 절반이 SSD:  벽에 끈적하게 들러붙은 핏자국  벽에 조각한 석상  콘크리트 바닥이 탄 자국  오크들이 벽에 페인트로 낙서질 해 놓은것  바닥에 쌓여있는 돌더미들  총알구멍  폭발자국  ......기타 등등등  특히 배경 아티스트들이 너무너무 좋아했어요~~~
  • 42.
    This slide hasa 16:9 media window SSD ON
  • 43.
    This slide hasa 16:9 media window SSD OFF
  • 44.
    구현 디테일 1. SSD를 제외한 메쉬들을 화면에 그림 2. SSD 상자를 그림(rasterization) 3. 각 픽셀마다 장면깊이(scene depth)를 읽어옴 4. 그 깊이로부터 3D 위치를 계산함 5. 그 3D 위치가 SSD 상자 밖이면 레젝션(rejection) 6. 그렇지 않으면 데칼 텍스처를 그림
  • 45.
    This slide has장면에서.. 이 a 16:9 media window
  • 46.
    이 데칼을 그려보죠 Thisslide has a 16:9 media window
  • 47.
    This SSD를 제외한메쉬들을 그림 1. slide has a 16:9 media window
  • 48.
    This slide SSDa상자를그림 window 2. has 16:9 media
  • 49.
    This slide SSDa상자를그림 window 2. has 16:9 media 하지만 이건 뭔가 아니잖아???? 이걸 프로젝터처럼 사용하고 싶음
  • 50.
    This slide hasa장면깊이를 읽어옴 3. 각 픽셀마다 16:9 media window
  • 51.
    4. 그 깊이로부터3D위치를 계산 float2 screenPosition = clipPosition.xy / clipPosition.w; float2 depth_uv = screenPosition * float2(0.5f, -0.5f) + float2(0.5f, 0.5f); depth_uv += ScreenDimension.zw; Half-pixel Offset Basically float sceneDepth = tex2D(DepthMap, depth_uv).r; float4 scenePosView = float4(clipPosition.xy * sceneDepth / (Deproject.xy * clipPosition.w), -depth, 1); Deproject.X = ProjectionMatrix.M11; Deproject.Y = ProjectionMatrix.M22;
  • 52.
    This 5. SSD상자밖이면, 리젝션 slide has a 16:9 media window 밖 안 밖
  • 53.
    5. SSD 상자밖이면리젝션 • 간단히 뷰공간의 위치를 SSD 상자의 물체공간으로 변환 • 위치가 0.5 보다 큰 픽셀은 상자 밖에 있는 것 position = mul(scenePosView, InvWorldView); clip(0.5f - abs(position.xyz));
  • 54.
    This 6. 상자안이면데칼을 그림 slide has a 16:9 media window // 데칼 텍스처의 UV float2 uv = position.xz; uv += 0.5f;
  • 55.
    그럼 조명은 거저먹음… Thisslide has a 16:9 media window Without SSD
  • 56.
    그럼 조명은 거저먹음… Thisslide has a 16:9 media window With SSD
  • 57.
    컴바이너 패스는 16:9media window This slide has a 그냥 동일과정 반복
  • 58.
    컴바이너 패스는 16:9media window This slide has a 그냥 동일과정 반복
  • 59.
    컴바이너 패스는 16:9media window This slide has a 그냥 동일과정 반복
  • 60.
    Mix-n-Match  아티스트는 Gbuffer또는 컴바이너 패스에 그려지지 않는 데칼을 만들수 있음  디퍼드 라이팅 엔진을 쓰기에 역시 공짜로 얻은 혜택
  • 61.
    This slide hasa+ Combinerwindow Gbuffer 16:9 media
  • 62.
    Gbuffer만 This slide hasa 16:9 media window
  • 63.
    Combiner 패스만 This slidehas a 16:9 media window
  • 64.
  • 65.
  • 66.
  • 67.
  • 68.
  • 69.
  • 70.
    아티스트에게 자유를….  아티스트는*.ssdecal 파일을 만듬 (사실 그냥 XML 파일)  레벨 에디터에서, SSD를 끌어다 놓음  이제부터 WYSIWYG. 각 인스턴스별로 수정도 가능
  • 71.
    문제점들 & 우리의해결책 1. 알파 블렌딩 2. 움직이는 물체들 3. 옆면이 늘어나요…. ㅜ.ㅜ 4. 짤린(clipped) 데칼 5. 성능
  • 72.
    1. 알파블렌딩 (법선) •컴바이너 패스에서 투명한 물체를 그리는 건 큰 문제없음 • 법선(normal)을 혼합 해야하는 Gbuffer가 문제 – 첫 구현: 알파테스트 사용 – 거의 마지막 구현: Crytek의 Best Fit Normal 기법 + 알파블렌딩 – 하지만 3 개월 뒤, 우리가 Best Fit Normal을 구현한 코드에서 버그 발견. 이전에 쓰던 법선저장법과 동일했음.. -_- – 그래도 법선 블렌딩이 이상하다고 불평하는 아티스트가 없었으니 시각적으로 문제가 없는 것… 그래서 그냥 그대로 뒀음… – 수학적으론 틀림… 하지만 게임개발에선 아티스트가 왕. 그러니 틀리든가 말던가…. (올해도 디스 당할지도…. -_-)
  • 73.
    1. 알파블렌딩(Spec Power) •Gbuffer의 알파채널에 Specular Power를 저장 • 일반적인 알파블렌딩 사용불가 – SSD 셰이더의 알파 출력(output)값은 RGB(법선) 혼합에 사용 – 해결책: Blend Factor! AlphaBlendFunction = BlendFunction.Add; AlphaSourceBlend = Blend.BlendFactor; AlphaDestinationBlend = Blend.InverseSourceAlpha; BlendFactor = ssd.SpecularPower / 255.0f;
  • 74.
    1. 알파 블렌딩(SpecPower) This slide has a 16:9 media window
  • 75.
    1. 알파블렌딩(Spec Power) Thisslide has a 16:9 media window Power = 128
  • 76.
    1. 알파블렌딩(Spec Power) Thisslide has a 16:9 media window Power = 40 Power = 128
  • 77.
    This slide hasa 16:9물체들 window 2. 움직이는 media
  • 78.
    This slide hasa 16:9물체들 window 2. 움직이는 media
  • 79.
    2. 움직이는 물체들 •움직이는 물체에 데칼을 붙여버릴 수도 있었음 • 하지만 스키닝 입힌 메쉬(예: 오크의 팔)은 여전히 문제 • 그래서 그냥 움직이는 물체에는 데칼을 그냥 안 적용했음… -_- • 초간단 스텐실 버퍼 기법으로 해결
  • 80.
    Stencil This slide hasa 16:9 media window
  • 81.
    This slide hasa 16:9물체들 window 2. 움직이는 media
  • 82.
    This3. 옆면이 늘어나요…ㅜ.ㅠ slide has a 16:9 media window
  • 83.
    3. 옆면이 늘어나요…ㅜ.ㅠ • SSD 상자의 투영면이 완전히 충돌하는 메쉬안에 들어가지 않을 때 발생하는 문제 • 처음발견한 문제, 여러가지 시도를 한 문제 • 하지만 데칼상자의 투영방향과 Gbuffer의 법선방향이 이루는 각이 어느정도 커지면 그냥 단순히 리젝션
  • 84.
    This3. 옆면이 늘어나요…ㅜ.ㅠ slide has a 16:9 media window 90 도
  • 85.
    3. 옆면이 늘어나요…ㅜ.ㅠ  아티스트가 지정한 각도 이상이면 무조건 픽셀 리젝션  180도로 지정하면 전혀 리젝션을 안함  대충 60도로 지정하는게 최고더라구요….?
  • 86.
    3. 옆면이 늘어나요…ㅜ.ㅠ 1. 정점 셰이더에서 데칼상자의 방위를 구함: output.Orientation = normalize(WorldView[1].xyz); 2. gNormalThreashold은 cos(각도) 3. 픽셀 셰이더에서 Gbuffer 법선을 읽어와 리젝션 테스트 float3 normal = DecodeGBufferNormal( tex2D( GNormalMap, depth_uv ) ); clip(dot(normal, orientation) - gNormalThreshold);
  • 87.
    3. 옆면이 늘어나요…ㅜ.ㅠ • 단순 리젝션 외에 우리가 시도해본 방법들 – 데칼상자의 방위와 정점법선이 이루는 각이 커짐에 따라 데칼이 서서히 사라지게 함: 둥근 파이프등에서 정말 안이쁨 -_- – 데칼상자의 방위와 Gbuffer 법선이 이루는 각이 커짐에 따라 데칼이 서서히 사라지게 함 • 이미 만들어놓은 데칼 텍스처들을 너무 흐리게 만들었음 • 노이즈가 많이 낀 gbuffer에서 아티스트들이 단순 리젝션을 더 선호했음 • 처음부터 이 방법을 썼으면 썼을지도… 여러분 게임에서 시도해 볼만한 가치는 있음
  • 88.
    4. 짤린(clipped) 데칼 •배경아트 데칼에서는 별로 문제가 아님 – 이미 배경 아티스트들이 성능상의 이유로 얇은(thin) 데칼을 사용 • 파티클에서 큰 폭발이 일어날때 종종 발생하는 문제 – 카메라가 데칼상자 안에 들어가면 – 픽셀이 래스터라이제이션 조차 안되서 생기는 문제
  • 89.
    This slide hasa 데칼 media window 4. 짤린 16:9 (OK)
  • 90.
    This slide hasa 데칼 media window 4. 짤린 16:9 (OK)
  • 91.
    4. Clipped Decal(BAD) This slide has a 16:9 media window
  • 92.
    4. Clipped Decal(BAD) This slide has a 16:9 media window
  • 93.
    4. 짤린 데칼(해결책) •카메라와 데칼이 충돌하면 • 뒷면(backface)을 대신 그림. 하지만 깊이 테스트 방향을 뒤집어야 함 • 하.지.만… 성능이… 마구 떨어져요…. – 깊이 테스트를 뒤집으면 계층적 깊이(Hi-Z)또 꺼져요.. ㅜ.ㅠ – 하지만 파티클 데칼에서만 문제가 되고, 이것에 대한 상상도못할 엄청난 해결책꼼수가 있음 (뒤를 보세요)
  • 94.
    This 4. 짤린데칼16:9 media window slide has a (뒷면 그리기)
  • 95.
    This 4. 짤린데칼16:9 media window slide has a (뒷면 그리기)
  • 96.
    5. 성능 • 어차피리젝션할 픽셀이라면 래스터라이제이션 조차 안하는게 좋음 • 깊이 테스트 방향을 뒤집어서 Hi-Z도 끄는걸 피해야 함 • 간단히 말해 데칼을 매우 얇게 만들 것 – 배경아트 데칼은 매우 쉽게 해결가능 = 노가다.... -_- – 파티클 데칼들은 노가다가 거의 불가능… • 이런 방침을 따른 스페이스마린은 파티클 데칼이 완전히 미쳐 날뛰지 않는한 언제나 30+ FPS로 실행 ^_^
  • 97.
    a 성능 This slide has5. 16:9 media window 이 데칼을 그리는 두가지 방법
  • 98.
    a 성능 This slide has5. 16:9 media window 엄청 두껍게
  • 99.
    a 성능 This slide has5. 16:9 media window 아니면 얇게
  • 100.
    a 성능 This slide has5. 16:9 media window 픽셀셰이더를 이만큼 낭비
  • 101.
    a 성능 This slidehas5. 16:9 media window 폭발물을 투척하는 오크가 많음
  • 102.
    a 성능 This slidehas5. 16:9 media window 그럼 이따만한 데칼들이 뒤에 남음
  • 103.
    a 성능 This slidehas5. 16:9 media window 그럼 이따만한 데칼들이 뒤에 남음 때론 이놈들 5개가 차곡차곡 겹치기도…
  • 104.
    a 성능 This slidehas5. 16:9 media window 그럼 이따만한 데칼들이 뒤에 남음 때론 이놈들 5개가 차곡차곡 겹치기도… 5 fullscreen 패스와 맞먹음 = 스페이스마린이 25 FPS까지 떨어지는 유일한 때 우리의 해결책? 꼼수?
  • 105.
    a 성능 This slidehas5. 16:9 media window 이것!
  • 106.
    a 성능 This slidehas5. 16:9 media window 이것! 오버레이로 숨겨요! 파티클로 발라요!
  • 107.
    a 성능 This slidehas5. 16:9 media window 이것! 오버레이로 숨겨요! 파티클로 발라요! 느려져도 눈치 못채는게 함정!
  • 108.
    a 성능 This slidehas5. 16:9 media window 이것! 오버레이로 숨겨요! 파티클로 발라요! 느려져도 눈치 못채는게 함정! 사실 이럴려고 한 건 아닌데… 덕분에 할일이 줄었..
  • 109.
    Special Thanks • 더이상자기 직원이 아닌데도 발표를 허락해준 Relic • 스페이스마린 렌더링 프로그래머들 • 아름다운 아트를 만들고, 렌더링 프로그래머를 맨날 괴롭혀준 아티스트들!
  • 110.
    More Special Thanks •온갖 탄압을 받으면서도 꿋꿋이 게임을 만드시는 한국 현직 게임개발자분들과 지망생분들… • 게임개발포에버 필자분들
  • 111.
    참조문헌 • ENGEL, W.2009, Designing a Renderer for Multiple Lights – The Light Pre-Pass Renderer. In ShaderX7: Advanced Rendering Techniques, Charles River Media • KAPLANYAN A. 2010, CryEngine 3: Reaching the Speed of Light, Siggraph 2011 • KRASSNIGG, J. 2010. A Deferred Decal Rendering Technique. In Game Engine Gems 1, Jones and Barlett • PERSSON, E. 2011. Volume Decal. In GPU Pro 2, A K Peters
  • 112.
    질문이 있으시다면 사진처럼친절하게 답해 드려요~ • 스페이스마린 렌더링 엔진 발표자료(KGC 2011) : http://kblog.popekim.com/2011/11/blog-post.html • Twitter:@BlindRendererKR (한글) @BlindRenderer(English) • E-mail: blindrenderer@gmail.com