번역/그 외2023. 2. 15. 02:43

작성기자: Joel Couture ( 2023.02.11 )

게임 개발자와 GDC는 모회사 Informa Tech산하의 형제 조직이다.

이 인터뷰는 Road to IGF 시리즈의 일부입니다. IGF는 게임 개발자의 혁신을 독려하고 매체를 발전시킨 인디 개발자들을 알리는 목적을 가지고 있습니다. 매년 게임 개발자들은 GDC에 앞서 IGF 수상자들과 자리를 가지며 각 분야의 주제들, 기획적 결정, 그리고 툴에 대해 알아가는 시간을 가집니다.

 

Outcry는 무명의 인물이 밤 동안 아파트에 갇히면서 편협한 이웃들을 상대하며 살육적인 새들과 생존권에 대해 다투는 모습을 보여줍니다.

Nuovo상을 수상한 팀의 게임 개발자 Quinn K., Kitet Frog, 그리고 Leaflet 함께 이야기를 했다.

충격적인 현실 세계의 정치적 움직임을 게임에 다루면서 오는 감정적인 도전들, 왜 하나의 결정이 게임의 핵심이 되었는지, 왜 실제로 변화를 주기 위해 괴로운 정치적 주제들에 달려들어야 하는 것이 필연적인지에 관해 이야기를 나누었다.

 

자기소개와 Outcry 개발에서 어떤 역할을 하셨는지 알려주실 수 있나요?

K.        : Quinn K., 28세입니다. 오스트리아에서 인디 게임개발자와 작가로서 활동하고 있습니다.

다양한 작업을 진행하였는데, 게임의 초상화, 배경 스프라이트들을 제작하고 대부분의 집필 업무를 하였고 팀을 만들기도 했습니다. OST도 조금 제작하였습니다.

               

Frog    :  Kitet Frog입니다. Outcry의 공동 디렉터 / 시각 연출자를 맡았습니다.

대부분의 컷신을 작업하고 팀의 다른 아티스트들을 감독하며, Quinn과 아이디어들을 계속 주고받는 등의 역할을 맡았습니다.

 

Leaflet : Leaflet입니다. 사운드 디자이너, 작곡가, 프랑스어 번역가로서 Outcry에 참여했습니다. 

게임 개발을 시작하게 된 배경이 어떻게 되나요?

K.        : Outcry는 제 첫 장편 게임인데요. 그전에는 여러 팬게임을 제작을 시작했다가 그만두거나, 다른 사람이 주도했던 많은 실패한 프로젝트들에 참여하기도 했습니다. 30분 정도 길이의 Twine 어드벤처 게임을 제작해보기도 했고요.

역주: Twine 어드벤쳐는 Twine을 활용하여 제작하는 웹 텍스쳐 게임을 의미하는 것으로 생각됩니다.

 

Frog    :  십대 초반 때부터 저는 게임을 만들고 싶어서 접근성이 쉬운 개발 툴을 익혔습니다. 비록 대부분의 시간을 친구들의 프로젝트에 그래픽 에셋들을 제공하는데 보냈지만요. RPGMaker 2003을 잠깐 써본 적이 있어서, 개발 엔진의 그래픽적 한계에 대해서도 알고 있었습니다.

 

Leaflet : 저는 게임 오디오 (Splateer, There Swings A Skull)와 내러티브 ( The Cartomancy Anthology )에 특화된 프리랜서입니다. 또한 게임개발에 대해 독학 했었습니다.

 

Outcry의 컨셉은 어떻게 나오게 되었나요?

K.        : 2016년 말, 저는 빈 외곽 지역에 거주했었습니다. 제 삶에서 가장 격동적일 때였던 것 같은데요. 어느 날 룸메이트도 나가서 없는데 휴대전화를 집에 놓고 실수로 문을 잠그고 나온 적이 있었습니다. 제가 할 수 있는 건 계속 주변을 방황하거나 아파트 밖에서 담배 피우는 것뿐이었죠. 건물 마당에서 몇 개의 벽돌을 보면서 많은 동물이 저를 주시하는 상상을 했습니다.

이것이 Outcry 개발로 이어지는 첫 자극이었으며 첫 번째로 Twine을 통해 대강적인 초안이 되었습니다. (지금은 없지만)

그때부터 살면서 여러 가지 일들이 생기고 정치적 문제들이 세계적으로 생겼습니다. 그렇게 아이디어는 처음의 자극보다 더 복잡한 무언가로 발전했습니다.

 

게임 제작에 어떤 개발 툴들을 활용했나요?

K.        :  제가 맡은 역할들과 관련하여 말씀드리면, RPG Maker 2003으로 게임을 개발하였고, GrapicsGale과 Aseprite로 그래픽 작업을 진행했습니다. 다른 분들은 Clip Studio Paint, Blender, SAI, Ableton 등을 사용하셨구요.

 

Outcry는 플레이어들을 많은 충격적인 현실의 이슈들을 다루는 가상의 세계로 초대하는데요.

무엇이 이런 주제들을 가진 내러티브 호러게임을 탐구하도록 또는 그래야 하게 느끼도록 만들었나요? 

K.        :  지금까지 살면서 2번 오스트리아는 공식적으로 극우성향의 정부가 있었습니다. 저는 사회적 안전망 시설에서 2번 정도 일했었고 많은 사람과 대화를 나눴습니다.

스토리에 대한 자극을 받았던 직후 미국에서 도널드 트럼프가 당선되었었는데요. 간단하게 말하자면, 이러한 정부의 정책에 겁먹거나 직접적인 영향을 받은 사람과 지냈고, 저를 포함해서 많은 사람이 이 시대에 큰 두려움을 가지며 살고 있다는 것을 알게 됐습니다. 이런 요소를 호러요소로 표현하면서, 게임이 그런 사람들에게 말하는 것처럼 된 것입니다.

역주: 사회적 안전망 시설은 원문에서 Communal safe space라고 표현하고 있습니다. 직역하면 공동 안전시설 정도이겠지만,

         답변에서 언급하는 트럼프, 유럽의 극우 열풍이 불었던 2010년대 당시 정치 상황을 고려하여 위와 같이 번역하였습니다.

Outcry는 이런 어려운 주제들을 다루면서도 움츠러들지 않는 모습을 보여줍니다.

무엇이 이런 주제들에 정면으로 부딪치도록 만들었나요? 왜 이런 문제들을 제대로 마주하는 게 중요한가요?

K.        :  왜냐하면 매우 현실적이고 많이 비주류이고, 실생활에서 가장 무서운 면들이기 때문입니다. 가차 없이 명확하게 주제들을 표현해서 애매모호함을 없애고 그런 문제에 영향을 받는 자들이 보인다고 느껴지게 만들어 그렇지 않은 사람들이 문제에 마주하게 하고 싶었습니다.

 

Frog   :  음, Outcry의 핵심 주제만큼 어려운 주제들을 다룰 때, 미묘한 것이 항상 최고의 아이디어는 아닙니다. 너무 미묘하면 잘되었다 해도 대부분의 플레이어가 비유를 놓칠 수 있습니다. 최악의 경우 당신의 작업이 적대자들의 이상을 상기시키는 긍정적인 상징으로 활용할 수 있으니까요.

 

창작자로서 이런 문제들을 다루는 창작물을 만들 때 어떤 어려움을 마주했나요?

감수해야 할 정신적 비용은 어떻게 했나요?

Frog   :  바보처럼 들리겠지만, 애초에 제가 메인 시나리오 라이터가 아니었기에 게임을 개발하는 동안 캐릭터들의 웃긴 우스꽝스러운 낙서를 많이 만들었습니다. 그냥 제가 원해서 그랬지만, 이게 팀의 활기를 유지해 줬다고 생각되네요.

주인공이 자기보다 큰 대마 담배를 피우면서 응원하는 그림을 가지고 있다면 게임 스토리에 의해 감정적으로 망가지기 조금 힘들지 않을까요?

 

K.        : 평생 충격에 충격을 계속 받아오면서 결과적으로 활기를 띠게 되었습니다. 창작활동을 하는 동안 감정을 다루는 법을 배우게 되었죠. 진짜로 그 질문의 반대가 맞는 것 같습니다. 어려운 문제에 정면으로 대응하는 이야기를 작성하면서 실생활에서 그에 대응되는 문제들을 다루는 데 도움이 됐습니다. 매일 일상에서 자신의 영향력을 경험하고 있는 사람이라면 이런 주제를 무시하기 어렵습니다. 오히려 반동분자들에 의해 이어지는 위협보다 이런 주제를 가지고 작성한 스토리들이 주는 문제가 덜 해로울 겁니다.

 

Leaflet : 전 운 좋게도 Outcry와 반대되는 경험을 가졌는데요. 게임을 개발하는 동안 신체적으로도 심적으로도 매우 안정적이고 긍정적이고 건강한 곳에 있었습니다.  그리고 매우 강력하게 정치적인 무언가에 얽혀있는 것처럼 느껴졌습니다.

때때로 매우 직설적인 게임의 분위기나 내러티브는 그런 행운을 좋게 쓰는 방법이었습니다. 만약 말이 된다면요.

 

게임에서 초반에 나오는 "Ignore or Follow" (무시하거나 따르거나), 이 선택을 기반으로 게임 전혀 다른 2개의 루트를 보여주는데요. 무엇이 이렇게 나누도록 만들었나요? 왜 이런 하나의 선택이 중요했나요?

K.        :첫 번째, 사람이 불의를 직면했을 때 2개의 선택지만 있기 때문입니다. 행동을 취하거나 가만히 있거나 지요.

이걸 "Follow"와 "Ignore"로 더 축약시키고 선택 창에서 적절히 보여주도록 했습니다.

두 번째, 이 게임은 Bertolt Brecht의 작품들에서 강하게 영감을 받았기 때문입니다.

( 그와 그의 제자들의 여러 작품으로부터 영감을 받았습니다.)

Brecht는 그의 희곡 중 일부를 2번 썼는데, "예" 또는 "아니요" 하나의 대답 달랐기 때문이었습니다. 이런 희곡들은 사회 교육 도구로 의도되었었고 Outcry도 그런 것입니다.

역주: Bertolt Brecht, 베를톨트 브레히트는 독일의 극작가, 시인, 그리고 연출자입니다. 

그의 희곡이 사회 교육 도구로 의도되었다는 말하는데, 이는 브레히트의 교육극 이론과 관련되어 있습니다. 

교육극을 대표하는 작품에서도 영향을 받아 이런 답변이 있었던 것 같네요.

더 자세한 건 이 링크에서 읽어보실 수 있습니다. ( 브레히트의 연극이론[발췌] / contributed by. Mary (tell2000)

새들과 시각적 요소 그리고 캐릭터들의 디자인에는 어떤 생각들이 들어갔나요?

Frog   :  중요하게 고려해야 했던 것은 때까치 새들(Shrikes)의 평범한, 악의 없는 새들과의 분리였습니다. 속일 수 있을 것처럼 평범해 보여야 했지만 (언동과 이념 외에도) 플레이어들이 폭력으로 스스로를 지켜도 기분 나쁘지 않도록 무서워야 했습니다. 

 

우리는 새들(Shrikes)을 담배 재로 구성되어 그들의 "깃털들"은 매우 벗겨지기 쉽게 층이 진 형태로 보이게 하고 마스크 뒤로 오렌지색 불빛이 은은하게 비추는 모습을 가지도록 컨셉 화하였습니다.

애초에 게임의 아트 리소스들은 상당히 낮은 해상도를 가졌기에, 이런 디자인 양상은 잘 된 것처럼 보였지만 꽤 미묘하긴 했습니다.

 

무엇이 새들이 차오르는 증오와 늘어나고 있는 악의에 찬 사람의 적절한 상징이라고 느끼게 했나요?

K.        : 여러 이유 중 하나는 제가 읽었던 Max Porter의 중편소설 [Grief is the Thing with Fethers]라는 소설을 읽을 때 나왔습니다. 화자 중 하나가 부주의한 말투로 생각나는 대로 말하는 새로 쉽게 흥미를 잃고 성급하게 결정하고 충동적으로 폭력을 행합니다. 게다가, 새의 눈은 항상 저를 소름 끼치게 했고, 이런 점은 Outcry의 분위기의 또 다른 핵심이기도 했습니다. 새들은 떼로 오기도 하고 이런 "물량의 힘"은 또 다른 증명된 은유적 도구이기도 합니다.

 

게임에서 까마귀들이 플레이어를 가로막을 때 방어 중심적 전투 시스템을 보여줍니다. 

어떻게 이런 시스템을 기획하게 됐나요? 자신을 보호하는 '전투'에 집중하게 하는 것처럼요.

(기자가 실수로 새들을 까마귀라고 지칭했습니다.)

K.        : 먼저 까마귀가 아니고, 때까치입니다. 때까치들은 맹금류의 일종이지만, 먹이를 가시에 꽂아놓는 새입니다. 상대를 죽이기 전에 살아남는 것을 강조하는 시스템을 만드는 게 주 아이디어였습니다. 또한 때까치 새들의 핵심 신조 "힘이 기하급수적으로 강해질수록 더 많은 것을 직면해야 한다는 사실"을 강화하기 위함도 있었습니다.

한 마리의 때까치 새를 상대하는 건 누워서 떡 먹기처럼 쉽지만, 여러 마리가 있다면 생존을 위한 전투가 됩니다. 개념적으로, 이건 자신의 생존을 보장하는 것이 당신을 증오하는 사회에서 저항하기 위한 수단임을 강조하기 위함이기도 했습니다.

 

Leaflet : 제가 이 주제에 기여한 건 많지 않지만, 무명인을 무적으로 만드는 *위업*을 첫 번째로 찾은 사람이란 것을 이번 기회를 통해 자랑하고 싶네요.

 

Outcry는 분노뿐만 아니라 동정심에 대한 요청처럼 느껴졌는데요.

플레이어가 이 경험을 통해 무엇을 떠올리길 바랐나요?

Frog   : 저는 행동에 대한 요구뿐만 아니라 자기 성찰에 대한 요구로도 보았습니다. 어떤 게임, 이야기든 관객에게 밖으로 나서서 무언가 변화를 만들라고 이야기할 수 있지만, "변화를 만드는 것"이라는 그들의 아이디어에 스스로 질문해 보지 않은 사람이 요청한다면 얼마나 효과적일까요?

 

K.        :사회가 거부하는 누군가를 도울 수 있을 때 행동하고 싶은 욕구처럼 무슬림에 대한 대중의 괴롭힘을 그들이 지나칠 때 한 명이라도 더 목소리를 내도록 하거나 인종차별주의 경찰들에게 대항하는 시위대에 한명이라도 더 함께하도록 할 수 있다면 우리의 목표가 달성된 것으로 생각합니다.

 

출처 : https://www.gamedeveloper.com/road-to-igf-2023/road-to-the-igf-2023-quinn-k-s-an-outcry

Posted by 텃파
유니티2022. 6. 20. 19:31

1-1. 여러 텍스처를 샘플링할때, Sampler

 

위와 같이 2개의 구가 있을때 양쪽의 구는 동일하게 가,나 텍스처를 불러온다.

셰이더에서 불러오는 방식이 다른데 이것으로 인해 생기는 차이를 알아보자.

 

좌측공은 combined, 우측공은 seperated 방식이다. (공식명칭X)

 

좌측은 텍스처를 sampler2D라는 HLSL로 우측은 TEXTURE2D라하는 매크로를 통해 불러온다.

(전처리 지시어, #define에 의해)

이러한 방식의 차이로 우측은 샘플러와 텍스처가 분리되었지만 좌측은 텍스처와 샘플러가 하나로 묶였다.

 

그렇다면 샘플러는 무엇인가?

렌더 파이프라인 상에서 텍스처를 처리할때 타일링을 할지, 필터링을 할지 등 어떻게 다뤄야할지에 대한 선택사항을 샘플러라고 한다.

 

위에서 설명한 차이로 생기는 결과를 살펴보도록 하자.

좌측은 합쳐진 형태이므로 텍스처와 샘플러가 한 덩어리이므로 2개의 텍스처를 사용했다면 샘플러도 2개이다.

우측은 분리된 형태이므로 텍스쳐는 2개이지만 샘플러는 공용으로 사용된다.

 

하나의 텍스처의 타일링 방식을 변경한 후 결과를 살펴보자.

 

사용된 텍스처 중 '가'텍스처의 Wrap mode를 Repeat에서 Clamp로 변경해보았다.

좌측 구는 '가'텍스처와 '나'텍스처가 서로 다른 샘플러를 사용하기때문에 '나'텍스처 영향을 주지 않았다.

우측 구는 '나'텍스처도 함께 영향을 받은 모습을 볼 수 있다.

이는 Wrap Mode외에도 Filter Mode를 변경하여도 비슷한 결과를 얻을 수 있다.

 

이번에는 '나' 텍스처의 Wrap Mode를 변경해보자.

좌측 구는 '나' 텍스처 부분에 영향이 그대로 보여진다.

우측 구는 '가' 텍스처를 변경한 것과 달리 변함이 없다.

 

이 결과를 통해서  우측 방식의 특징을 명확히 확인할 수 있는데,

'가'텍스처의 샘플러를 '나'텍스처가 공유하여 '나' 텍스처만의 샘플러가 없는 것을 알 수있다.

위의 경우 '나'텍스처의 샘플러가 따로 없고 '가'의 샘플러를 같이 사용하기에 변함이 없는 것이다.

 

코드를 살펴보면 더욱 명확히 알 수 있다.

'가'텍스처 와 '나'텍스처가 하나의 샘플러를 통해서 불러옴을 알 수 있다.

하드웨어의 제약 등으로 인해서 샘플러의 수에 제약이 있을때 이러한 방식을 사용한다.

제약이 많은 샘플러는 적은 수로 사용하고 텍스처는 다양하게 쓰기 위함이다.

 

메뉴얼 상에서도 아래와 같은 내용이 있는데

"많은 그래픽스 API의 GPU에서는 텍스처보다 적은 샘플러를 사용할 수 있으며~"

한정된 자원에서 최대한의 성능을 이끌어내기 위해서 분리된 방식을 사용한다.

combined(연결된)방식이든 sepreted(분리된)방식이든 _ST를 꼭 붙여주어야한다.

TRANSFORM_TEX의 경우 유니티에서 define매크로 처리에 의해

_BaseMap의 키워드를 기준으로 _ST 이름으로 자동 변환되어서 사용하며,

SAMPLER(sampler_BaseMap)에서 또한 _BaseMap 이름을 기준으로 _미리 약속된 처리를 한다.

일종의 약속된 규칙이다.

 

1-2. UV회전

 

회전 행렬을 복기하여 보자. ( 이미지 출처 )

uv의 경우 x,y 가로세로의 평면 회전이기에 이동할 필요가 없는 경우 동차좌표를 사용하지 않아도 된다.

 

예재를 통해 이해보도록 하자.

예제 코드의 결과물 예시

UV회전을 회전행렬을 생성시키는 함수를 호출한다.

해당 함수는 RotMatrix로 아래와 같이 구성된다.

함수에서 2x2 크기의 행렬을 구성해서 return함을 알 수 있다.

 

이렇게 계산된 행렬을 uv정보와 mul을 통해서 곱하는데 코드에서는 Offset and Tilling을 고려하여 원점으로 돌리고나서

해당 과정을 거침을 볼 수 있다.

Tilling을 하게되면 pivot에 변화가 생기는데

TRANSFORM_TEX가 타일링과 오프셋을 감안해서 uv정보를 가공하여 준다.

 

이 과정이 없다면 무조건 원점을 기준으로 돌아가게 되어 아래와 같은 결과를 얻게된다.

2-1. Diffuse Wrap (Toon Ramp) , Colorlize

 

아래 예재를 보도록하자. 

 

좌: Diffuse Wrap 예재 / 우: 램버트 라이팅 예재

좌측 예재 오브젝트는 N(노멀)dotL(라이트)한 렘버트 셰이딩 값인 1 ~ -1의 값을 기반으로

Ramp Map을 샘플링 한것이다.

RampMap텍스처는 아래와 같다

좌하단이 (0,0) / 중앙 ( 0.5, 0.5) / 우상단 (1,1)

코드를 보도록 하자.

코드 일부 발췌

SAMPLE_TEXTURE2D라는 매크로에 의해 텍스처와 uv를 불러오고있다.

~ (_RampMap, sampler_RampMap, ~ / 텍스처와 샘플러가 분리된 방식으로 불러오고 있다.

유니티 메뉴얼 [ 텍스처 그리기] 일부 발췌

uv를 half2(NdotL, 0.5)라는 코드로 불러오는데, 텍스처를 얻어올때 uv의 세로 값을 0.5로 고정하고있다.

 

가로방향으로 NdotL을 사용하고 있다.

발췌 코드 2번째 줄을 보면 1~-1로 가던 NdotL을 1~0으로 가는 Half Lambert로 가공하고있다.

이 코드를 거친 결과 빛을 제일 많이 받는 구간은 1쪽에서 색을 얻어오고, 반대는 0쪽에서 얻어올것이다.

결과적으로 라이팅을 아래 그라데이션처럼 그리게 되는것이다.

좌하단이 (0,0) / 중앙 ( 0.5, 0.5) / 우상단 (1,1)

리턴을 단순히 NdotL로 받았다면 아래 좌측과 같은 형태가 되었겠지만 uv를 통해 색을 얻어옴으로서 그라데이션의 색을 얻어온것이다.

이 방식을 사용할때 텍스처의 Wrap Mode를 Clamp로 해주어야한다.

Repeat이라면 색이 제일 밝거나 어두운곳에서 텍스처의 타일링으로 의도치 않은 색끼어듬이 발생할 것이다.

또한 비압축을 권장한다.

또한 텍스처의 세로크기가 1pixel크기여도 된다.

만약 하나의 그라데이션만 있는것이 아니고 하나의 텍스처의 여러 그라데이션을 세로로 쌓아놓을수도 있는데,

위 예재 코드에서 uv의 세로값을 0.5로 고정하여 얻어온 것처럼 목적에 맞추어 세로 uv값을 달리하여 얻어오면 된다.

다만 이 경우 세로 uv정보에 어떤 위치는 어떤 그라데이션인지 개발 내부적으로 약속을 할 필요가 있다.

 

Ramp텍스처는 글로벌 텍스처로 사용하기도 한다.

라이팅은 글로벌한 값이므로 하나의 씬안에 라이팅을 받을 수 있는 오브젝트나 재질이 여러가지 일수도 있기때문이다.

아티스트가 매번 서로 다른 재질마다 일일히 다른 Ramp텍스처를 지정하는건 위험부담이 크다.

개발팀마다 사정이 다르겠지만, 씬내에 빈 오브젝트 생성하여 플머가 만든 컴포넌트를 달고 여기에 씬에 사용되는 라이팅 용 그라디언트 세팅을 담는다. 플머는 컴포넌트 코딩 시 글로벌 프로퍼티를 세팅한다.

아티스트는 셰이더를 코딩할때 이러한 세팅이 있다는 가정하에 셰이더에서 프로퍼티를 사용하지않고 HLSL로 바로 가져다 사용한다.

(ex 셰이더에서 재질과 관련된 프로퍼티를 작성하지 않고, 글로벌 프로퍼티를 가져온다는 가정하에 바로 사용)

 

이러한 방식은 Colorize에서도 사용된다.

GrayScale로 작업된 이펙트 텍스처의 밝기정보를 이용하여 그라디언트 텍스처를 샘플링하는 것이다.

여러개의 그라디언트를 하나의 텍스처에 층지어 쌓고 재질에서 uv값을 통해 여러개의 다양한 색상을 가져오는것이다.

 

3-1. 굴절

화면을 캡처하여 Distortion을 적용하는 간단한 방식으로 정확한 Ray Tracing이 아니다.

URP에서는 Geometry Reder Queue 2000번 시점에서 렌더 파이프라인이 화면을 캡처하여 _CameraOpaqueTexture라는

글로벌 변수에 텍스처를 매 프레임 설정한다.

이는 아래 이미지와 같이 렌더 파이프라인 에셋에서 Opaque Texture를 체크해야 캡처가 수행된다.

(레거시 렌더 파이프라인에서는 Grab Pass에 의해 재질이 그려질 때 캡처를 수행한다.)

 

굴절 오브젝트는 반투명, 뒤에 있는 바닥 등은 불투명한 오브젝트이다.

실제로 렌더 파이프라인의 그리는 순서도 불투명 오브젝트를 그리고나서 Transparet를 그린다.(렌더큐)

Opaque와 Transparent사이에 매프레임마다 Opaque를 캡처하여 사용할수 있게 준비하는 것이다.

(캡쳐 결과는 렌더링한2D이미지,반투명없는상태,uv좌표도 있음)

좌 : Opaque Texture를 끈 상태의 결과물 / 우: 굴절셰이더의 UV가공을 전부 주석처리한 후 color값에 0.5를 더한 결과물 
IN.uv.x += 0.1; 을 코드에 입력하여 약간 옆의 이미지를 그리게 한 결과물 (좌 원본 / 우 가공 결과 )

 

 

관련 코드 알아보기(접은글)

더보기

UV는 코드의 어디에서 가져오는가?

IN.uv가 값을 얻어오는 부분은 강조 된 부분으로 ComputerScreenUV함수로 클립공간의 버텍스를 기준으로 화면좌표를 계산 받는 부분이다.

그리려고 하는 픽셀이 화면상에서 가로세로 어느 위치에 있는지 알고싶을때 ComputerScreenUV함수를 사용한다.

 

굴절 구현에 있어서 프레넬이 사용된 것을 볼 수 있다.

프레넬 구현 코드 아래를 보면 IN.normalISS 라는 생소한 구문이 보인다.

이는 ScreenSpaceNormal을 버텍스 셰이더에서 계산해 온 값이다.

 

코드를 살펴보면 아래와 같이 이해할 수 있다.

Attribute 구조체에 의해 들어온 normalOS가

vertex셰이더에서 IN이라는 구조체 함수에 의해 오브젝트공간에서 클립공간으로 공간변환이 된다.

클립공간 노멀 정보중에 xy값만 따로 계산하는데 클립공간기준 좌우와 상하 방향만 사용한다는 것인데, 

클립공간은 보는 카메라 방향인 것을 생각하면 카메라 방향에서 좌우상하만 따로 사용하는 것이다.

xy공간만 스크린스페이스 노멀(normalSS)에 저장을하고

xy만 사용하여 길이가 1이 아니게 되버리기에 정규화(noramlize)한다.

이런 정보가 저장된 것이 OUT.normalSS인것이다.

화면을 보는 기준에서의 픽셀의 프레넬 정보가 normalSS인 것.

결론은 프레넬 정보를 기준으로 uv를 밀어서 찍는 것이다.

CameraOpaqueTexutre에서 IN.uv로 색을 얻어오는데 IN.uv는 아래와 같이 가공을 거치는 부분이 있는데,

프레넬(fresnel) 만큼 uv를 밀어서(IN.normalSS) IN.uv를 가공겠다는 뜻이 되는것이다.

_Refraction은 프레넬 외에 얼마나 증폭할지 정하는 부분이다.

_Refraction으로 증폭된 모습 ( 좌: 원본 / 우: 가공 결과물 )

 

 

아래는 반사에 관련된 내용들이다.

GlossyEnvironmentReflection는 반사를 계산해주는 함수이다.

 

 

좌: 반사만 100% 본 모습 / 우: reflect에 프레넬을 곱한 모습

그렇게 얻은 reflect를 원래색과 굴절사이에서 얼마나 반사(reflect)할지 보간을 한다.

reflectAmount에서 _Reflection은 인스펙터에서 조절 가능한 값으로 반사의 정도를 조정하고자 하기위함이다.

위에 더보기를 누르면 글이 펼쳐집니다.

 

 

굴절 오브젝트 뒤에 굴절 오브젝트의 모습이 안보이는 것을 볼수있다.

CameraOpaqueTexture는 2000번대 Opaque렌더큐를 마치고 나서 준비된 이미지이기에

굴절 오브젝트가 그려지기 전의 이미지를 가공하여 사용했기에 보이지 않는 것이다.

 

Legacy와 달리 URP에서는 최적화 이슈로 Opaque텍스처를 지정된 순간 한번 찍고 마는데, Legacy에서는 촬영 지시를 GrabPass를 통해 셰이더에서 하는 것이 가능했다.

관련 링크

 Grab Pass라는 Pass를 끼워넣으면 재질이 셰이더를 렌더링할때 캡쳐를 진행한다.

서로 다른 Grab Pass를 든 오브젝트가 여럿있으면 그만큼 캡쳐를 진행하는 것이다.

다만 그런 오브젝트가 많아질수록 기하급수적으로 성능저하가 생기기 쉬운데,

URP에서는 엔진이 성능의 최적화를 위해 어쩔수없이 그렇게 된듯하다.


그 외 참고자료 (접은 글)

더보기
레거시에서의 구현방식

URP에서는 GlossyEnvironmentReflection(월드반사벡터,WorldSpace위치,roughness,Occlusion)를 통해 구현.

Lighting.hlsl의 GlobalIllumination.hlsl에서 확인가능

 

 

4-1. 노멀맵

 

버텍스 기준의 노멀 정보로 지금까지 라이팅하는 법을 배웠지만

노멀맵의 사용은 픽셀단위로 방향값을 텍스처로 제어해보자는 취지에서 시작하였다.

노멀맵 텍스처는 픽셀의 방향단위를 가진 텍스처이다.

노멀맵의 사용예시

 

 

아래 예재를 통해 이해해보자.

좌측과 같이 울퉁불퉁한것 없는 평명 Plane이지만 우측과 같이 라이트의 방향에 따라서 다르게 보이는것이 보이는가?

위의 평면 오브젝트는 아래와 같이 노멀맵이 적용되어 있다.

적용되어있는 노멀맵 텍스처를 포토샵에서 불러와서 채널을 보면 아래와 같이 되어있는 것을 볼 수 있다.

R채널은 좌우에 대한 정보를, G채널은 상하, B채널은 앞뒤 대한 정보를 가진다.

더 이해하기 쉬운 예재로 보도록하자.

좌측의 이미지는 노멀맵, R채널, G채널, B채널 순으로 열거한 이미지이다.

좌측의 이미지에 라이팅이 얹어지면 우측처럼 라이팅이 렌더링된다.

 

차이가 가장 극명한 R채널을 유심히 보도록 하자.

 

우측 이미지는 각 지점을 스포이드로 찍어 컬러의 RGB값을 본 것이다.

R채널은 좌우에 대한 정보를 가진다고 위해서 설명하였다.

 

쉽게 생각해서 -1~1을 0~255로 나타낸것이다.

 

자세한 설명이 있는 글

[study] 노멀맵은 왜 파랗게 보일까? / by. gardiss

 

차후 설명 보강 예정

 

 

 

 

 

 

*노멀맵* 을 사용할 때 OpenGL용인지 DirectX용인지 구분하여 사용하여야한다.

참고링크 OpenGL, DirectX용 노멀맵을 구분하는 방법

그 이유는 서로 RGB에서 G채널의 계산이 서로 반대이기 떄문이다.

 

 

번외. 픽셀아트를 위한 노멀맵 생성 툴

 

필자가 사용해본 2가지 노멀맵 생성툴을 소개하겠다.

 

1.SpriteLamp

 

사용자가 상,하,좌,우,앞 에서 어떻게 빛을 받을지 Grayscale로 만들어주면 몇가지 설정을 통해서 노멀맵을 생성해준다.

노멀맵 외에도 Depth map과 Ambient occlusion map도 생성가능하다.

다만, 무료 툴은 아니고 유료 툴이다.

 

2. Laigter

 

이미지를 집어넣으면 사용자는 생성하고자 하는 맵의 설정을 조금식 건들여주면 자동으로 노멀맵을 생성해준다.

노멀맵 외에도 Specular맵, Parallax맵(노멀맵보다 발전된 형태로 알고있음.), Occlusion맵을 만들 수 있다.

SpriteLamp와 달리 오픈소스 프리웨어로 접근성이 좋다.

다만, 설정수치에 따른 완전자동생성형이므로

자율성은 조금 떨어지는 편이다.

 

'유니티' 카테고리의 다른 글

13강 (14주차 진행)  (0) 2022.06.09
12강 (13주차 진행)  (0) 2022.06.01
11강(12주차진행)  (0) 2022.05.25
10강 (11주차)  (0) 2022.05.18
9강 (10주차)  (0) 2022.05.10
Posted by 텃파
유니티2022. 6. 9. 00:01

0. 지난주차 보충 [ 접은 글 ]

 

0-1. 동차 좌표 - 차원을 늘려서 민다는 무엇인가?

 

우선 간단한 1차원 벡터로 접근을 해보자

기저벡터는 1이다.

x가 1이라면 기저벡터 1에 의해 변환되는 값은 1, 기저벡터가 0.5라면 0.5가 될것이다.

즉, 1이라는 기저벡터 대신 다른 값이 들어가면 해당 값으로 스케일 변환되는 1차원 벡터에 의한 행렬이다.

이동 기능을 위해 한 차원을 더했다고 해보자.

y축이 늘어 xy평면이 됨

이 평면의 y축 기저벡터를 오른쪽으로 a만큼 밀면 평행사변형 모양으로 비틀어진다.

이때 a를 0.7 y를 1이라고 가정해보자. 그렇다면 x가 0.5일대 (1.2 , 1 ) 의 위치가 된다.

이 상태에서 y차원 하나를 무시하여 생각해보자. x값이 0.5에서 a값인 0.7만큼 밀어내어 최종적으로 1.2로 이동하였다.

축을 하나 추가하여 기저벡터를 밀고, 하나의 축을 버려 이동값을 나타내는 것이다.

같은 방식으로 2차원,3차원도 할 수 있다.

 

이상 차원을 늘려 이동한다! 에 대한 보충 설명이다.

 

0-2. 클립공간의 Z, 뷰 공간의 Z

 

view 공간에서 z값을 조정한다하면 view좌표계에서 앞뒤로 움직이면 결과물은 커지고 작아질것이다.

Projection공간에서는 투영이 적용되어있고 View와 달리 평행한 좌표계이다.

평행한 좌표계에서 vertex가 가까이 있는 것이 커보이도록 커지게만 되어있는것이다.

원근감이 없는 orthographic 카메라에서 다시 되돌려생각해보자.

즉 원근감이 없는 공간인데, 폴리곤 자체는 이미 원근감에 맞추어 커지고 작아져있다.

이 상태에서 z값이 이동되면 어떻게 될것인가?

원근감이 없기때문에 가까이 와도 커지거나 작아지지 않는다. 원근감은 이미 process되었고 평행한 좌표계이기 떄문.

z값을 떙겨도 멀어지고 가까워지고 하지만, 크기는 차이가 없는 결과물을 가진다.

 

0-3. 변환의 결합

기존에는 SRM으로 설명하였는데 순서가 중요하여 MRS로 수업자료를 변경하였음 결합의 순서도 중요하기 때문

그럼에 따라서 순서를 이동,회전,크기 행렬로 변경하였음.

인터넷에서 볼수있는 T(=Movement)RS와 일맥상통한것.

 

1-1.아웃라인 셰이더 원리

지난주차에서는 이 링크에서 설명하는 방법으로 3ds Max로 아웃라인을 제작하면서 원리를 살펴보았다.

해당 방법을로 알 수 있는 외곽선의 원리는 다음과 같다.

하나의 물체에서 외곽선이 생기는것이 아닌, 실제 물체와 외곽선 물체로 2번 그려낸다.

외곽선 물체는 면을 뒤집어(앞면을 culling처리) Vertex를 확장시켜준다.

외곽선 물체 위에 실제 물체가 올라온다.

다음으로 URP 셰이더의 멀티패스로 아웃라인을 살펴보자.

 

우선 멀티패스 방식이므로 

Edit -> Project Settings -> Graphics의 Scriptable Render Pipline Setting 에셋에서 수업자료로 제공된 PassTest 렌더러로 대체한다.

Outline 패스를 그리게 된다.

수업자료로 제공된 씬에서 아웃라인과 2Pass 반투명 효과를 확인할 수 있다.

Attribute이라는 구조체 형식으로 버텍스 셰이더에서 IN이라는 구조체 변수로 포지션과 노말정보를 받아들인다.

코드에서 _OutLineDistance는 단순히 해당값만큼 Vertex를 확장시키는데, 원근 교정에서 문제가 생긴다.

가까이에서 아웃라인을 보면 선이 두껍고 멀리서 보면 얇은 것이다.

일반적인 툰쉐이딩 게임에서는 가까이서 보면 선이 얇아지고 멀리있다면 두꺼워진다.

 

원근 교정을 적용시키기위해서 우리는 카메라와의 거리 Clip 공간에서의 W값, View공간에서의 z값을 떠올릴수있다.

거리가 작아지면 결과값도 작아져야하고 거리가 커지면 결과값도 값이 커져야하는데 이는 결국 거리값을 곱하면 된다는 것이다.

아웃라인두께 수치에 거리값을 곱하고 거기에 노멀 벡터를 곱하여 원래 버텍스 포지션에 더해주어

거리에 따라 두께가 대응되는 결과물을 얻을 수 있다.

이 방법은 월드 좌표계의 노멀 이동 방식 + 원근 교정 방식이다.

또한 셰이더의 Pass Command를 보면 Z버퍼에 기록을 안한다. (ZWrite Off)

정해진 방식은 없지만 예제 코드에서는 아웃라인 폴리곤이 Z 공간에 기록하지 않도록하여 2D 포스트 프로세싱같은 느낌접근한 형태이다.

Cull Front가 핵심적인 부분으로, 뒤집혀 그려져야하므로 뒷면만 그려지도록 하는 것이다.

그려지는 순서도 잘 조정해주어야한다. AfterRendringSkyBox를 추천. 다만, 실제 개발환경을 고려해야 한다.

 

다만 Vertex offset 방식의 아웃라인은 단명 폴리곤에 사용할 수 없다.

로우 폴리캐릭터를 만들다보면 머리카락을 평면으로 심어놓는 경우가 많은데 이 경우가 예시가 된다.

offset방식은 머리카락도 모두 덩어리가 모든 방향으로 있어주어야한다.

평면을 노멀방향으로 확장시키고 뒷면만 그리게 하면 아무것도 안그려지는 것.

덩어리가 있는 머리카락이어야지 노멀방향으로 확장이 되어 아웃라인을 그릴수있다.

연산이 가볍고 Draw Call을 한번 더 먹긴 하지만 모바일 환경에서도 사용하기 편하다. 다만 위와 같은 환경에 대응을 못하고, 노멀이 끊킨 경우 서로 다른방향으로 나뉘어 확장된다.

 

1-2. Post Effect에서의 아웃라인 셰이더

https://github.com/Unity-Technologies/UniversalRenderingExamples

유니티에서 제공하는 2D 포스트 이펙트에서 구현하는 아웃라인 샘플으로 아래와 같은 장점 단점을 가진다.

-장점 : 버텍스 노멀 방식의 폴리곤이 갈라지는 현상이 없다.

-단점 : 포스트 이펙트 태생적인 문제로 모바일에서 느리다.

 

 

공식 해설 영상 링크

 

 

2-1. BRDF

 

한글로는 양방향반사도분포함수로 영어로는 Bidirectional Reflectance Distribution Function 라고 한다.

[ Bi (두 방향의) + directional (방향, 지항성의) / Reflectance(반사율) / Distribution (분포) / Function (함수) ]

2개의 입사각과 반사각이 존재할 때 어떤 식으로 빛이 반사되는지, 정도를 계산하는 함수를 BRDF 라 한다.

입사되는 빛을 어떻게 반사할지 계산하는 공식은 모두 BRDF이다.

ωi는 불투명한 표면의 한 점에서 광원을 향하는 벡터이다.

ωr은 불투명한 표면의 한 점에서 관측자 또는 카메라를 향한 벡터이다. ωo로 표기되기도 한다.

n은 표면의 노멀 벡터이다.

이런 조건에서 어떻게 반사되는지 함수로 정의한 fr(ωi,wr)함수가 BRDF이다.

ex) Lamber, Blinn-Phong, Phong 등등

 

 

BTDF이라고 투과 함수 도 있다.

디즈니는 사실적이면서 아티스트가 다루시 쉬운 BRDF를 꾸준히 연구해 왔고 아래 링크에서 관련자료를 볼 수 있다.

링크

디즈니 BRDF Explorere

 

그외 다른 링크 BRDF - Walapon

 

2-2. 하프 램버트 (Half Lambert)

 

Valave의 하프라이프에서 도입한 라이팅 방식으로 가벼운 계산에 비해 시각적인 결과가 좋다.

Lambert느낌은 ambient가 적용되지않아 타버리는 느낌이 나는데 죠죠 극화체, 미국 히어로 코믹스 느낌 같은 극히 일부가 아닌 이상 잘사용되지않는다.

기존 램버트 셰이딩에서 dot 연산결과에 0.5를 곱하고 0.5를 더하여 0~1값으로 변형 시킨다.

옛날 환경광 처리를 잘 할수 없던 열약한 하드웨어 상황에서 가벼운 계산으로 GI라이팅 효과를 내고자하는 편법으로 사용되었고, 요즘은 풍부한  글로벌 라이팅 효과를 얻을 수 있어서 잘 사용하지 않는다.

오히려 GI 환경 라이트와 같이 사용할 경우 너무 밝아져 정확한 라이팅을 해치는 요소가 될 수 있다.

 

현재는 ambient를 정확히 계산하는 방식을 사용하며, 예시로는 언리얼의 루멘이다.

 

 

3-1. 정반사 (Specular)

 

정반사는 금속과 비금속의 정반사가 다른 특징을 보이는데

금속의 정반사는 거울처럼 주변을 완전하게 보여준다.

https://commons.wikimedia.org/wiki/File:Chrome_ball_in_Ginza.jpg

반면에 비 금속은 당구공이나 대리석처럼 표면을 아무리 매끄럽게 가공해도 난반사가 정반사와 함께 발생한다.

정반사와 난반사가 함께 뒤섞여 발생하면서 상대정으로 빛이 강한 광원이 유난히 잘 보이는 것일 뿐 실제로는 주변환경이 다 반사된다.

https://pixabay.com/photos/eight-ball-8-ball-8-ball-eight-3721944/

과거에는 가벼운 연산으로 정반사 효과를 표현하기 위해 동그란 모양의 밝은 하이라이트를 더해서 사용했었다.

주변을 반사하는 정반사라고 보기 어렵고 PBS의 에너지 보존법칙에 위배되지만 셰이더를 배우기위해 기초지식으로

알아야 하는 내용이다.

 

3-2.  퐁(Phong)

https://www.scratchapixel.com/lessons/3d-basic-rendering/phong-shader-BRDF

반사벡터 R과 viewDir벡터 V를 dot연산을 한다.

reflect 함수를 사용하여 Blinn Phong에 비해 무겁다.

reflect 함수에 뒤집힌 빛의 방향 벡터와 노멀방향을 넣어 반사벡터 R을 구하고 뷰벡터와 dot하여 Specular을 구한다.

더보기

http://www.silverwolf.co.kr/shader/79529 <- HLSL내장함수 / by.은빛늑대 

reflect(i, n) : 정반사광의 방향 벡터를 구하는 벡터반사 함수.

                      첫 번째 인자로 입사광의 방향벡터를 두 번째 인자로 반사면의 법선을 받는다.

R벡터와 V벡터간의 각도를 구하여 얼마나 빛이 눈에 잘들어오느냐를 구하게된다. Lambert에서의 Dot연산을 연상해보자.

구한 Specular에 대해서는 pow함수를 거치는데 _SpecPower값을 높이면 높일수록 흰색 점이 점점 작고 또렷하게 된다.

 

다만 코드에서 Fragment 부분을 보면 정규화를 거친다.

IN.normal로 들어오는 값은 버텍스 셰이더에서 계산한 오브젝트 공간의 노멀벡터를 월드공간으로 변환한 직후의 노멀이 들어온다.

이때 프레그먼트 셰이더는 픽셀마다 전부 계산하는데

여러개의 픽셀이 존재할때 중간 픽셀에 있는 노멀값은 자동으로 보간되어 들어오는데 Interpolator를 거치면서 미묘하게 짧아지는 노멀이 생기게된다.

초록벡터: 버텍스 셰이더에서 계산한 노멀 / 파란벡터: 프래그먼트 셰이더로 전달된 보간 노멀, 미묘하게 짧아진다.

아래는 그 미묘한 차이를 pow함수를 통해 시각화한 모습이다.

좌: normalize를 하지 않은 모습 / 우: normalize를 거친 모습

 

3-3. Blinn Phong 블린 퐁

벡터 크기는 정규화 되었음.

( 하프 벡터 ) H벡터가 핵심으로 LightDir 벡터와 ViewDir 벡터를 더해서 계산한다.

블린 퐁은 H 벡터와 표면의 노멀 벡터 방향이 일치하는지 dot 연산을 진행한다.

 

V벡터를 R벡터(블린 퐁에선 미사용)에 합쳐졌다고 가정해보자. 그렇다면 H벡터가 노멀벡터와 일치될것이다.

퐁에서는 V벡터가 R벡터랑 합쳐질수록 밝아지는 것이었지만, 블린 퐁에서는 R벡터에 근접할수록 노멀벡터와 H벡터가 교차되어 밝아지는 것이다.

reflect함수를 사용하는것보다 V벡터와 L벡터를 더하는것이 연산이 가볍다.

가장자리의 차이를 보시라.

퐁과 블린 퐁은 미묘하게 다른데, 중심부는 비슷하지만 가장자리가 미묘하게 다르게 그려진다.

큰 차이가 없기에 더 가벼운 블린 퐁을 많이 사용한다.

좌: 퐁 / 우: 블린 퐁

3-4. 프레넬 (Fresnel), 림 라이트

 

노멀 방향과 뷰방향을 dot하고 OneMinus를 한다.

물리적으로 정확한 프레넬은 아니고 단순하고 가벼운 방식이다.

렘버트 셰이딩에서 광원이 아닌 viewDir을 사용한다면 프레넬!

빛과 무관하게 내가 바라보는 각도와 노멀방향이 얼마나 일치하는지만 검사한다.

 

dot 결과를 saturate해서 0~1로 만든 뒤 OneMinus처리로 뒤집는다.

코드를 보면 pow연산를 하는데 Power를 통해 프레넬효과가 얼마나 두껍게 생길지를 조절한다.

사용예시

3-5. Lambert의 픽셀 라이팅과 버텍스 라이팅

 

 

좌: 버텍스에서 라이팅 진행 / 우 : 픽셀에서 라이팅 진행

좌처럼 버텍스에서 셰이딩하는 방식을 고러드 셰이딩(Gouraud Shading)이라고 한다.

버텍스에서 셰이딩한 결과를 보간해서 사용하는데, 램버트 라이팅을 버텍스에서 진행하고 라이팅 값을 픽셀 셰이더에 보간하여 전달한다.

결과적으로 dot한 값은 구조체에 담겨 픽셀셰이더에 전달되어 픽셀셰이더에서의 ndot값은 버텍스 셰이더에서 계산한 값을 보간기가 보간한 값이 된다. 그러한 결과에서 퀄리티 차이가 나는 것이다.

다만 연산은 압도적으로 버텍스에서 라이팅한 방식이 가벼워진다.

 

픽셀 셰이더에서 할 연산을 버텍스 셰이더에서 했을때의 장단점은 아래와 같다.

 

장점

 - 셰이더 연산이 가벼워진다.

 - 단순 Lambert 셰이딩은 퀄리티가 나쁘지 않다.

단점

 - 림라이트나 스페큘러 등의 뚜렷한 셰이딩은 낮은 퀄리티

 - 셰이더 관리가 복잡해진다. (전달 구조체 내용이 달라진다.)

좌 : 버텍스에서 연산 / 우: 픽셀에서 연산

   프로젝트의 대부분의 셰이딩 연산을 픽셀 기준으로 처리한다면 전달 구조체가 일관성 있게 관리될 수 있음.

   대부분 셰이딩은 픽셀 셰이더에서 처리하는게 퀄리티도 좋고 구조체 관리가 깔끔하다.

그림 1,2 : 버텍스 셰이딩 방식 /  그림3 : 좌측 픽셀  방식, 우측 버텍스 방식

버텍스와 버텍스 사이의 중간 픽셀은 보간(Interpolation) 되어서 프래그먼트 셰이더로 전달되며 Gouraud Shading이라한다.

 

그외 참고링크

Unity PBR Specular BRDF : URP migiration (33분 44초)

유니티 - 본격적인 PBR쉐이더(Cook-Torrance)

GGX라는 용어에 대해 -> Specular BRDF Reference

 

4-1. IBL(Image Based Lighting), 구면조화함수 SH (Spherical Harmonics )

IBL은 정반사(Specular)와 난반사(Diffuse) 정보를 큐브 텍스처로부터 얻어서 라이팅을 하는데

서브서턴스 페인터의 환경맵 라이팅이 좋은 예시이다.

코끝의 환경컬러가 어떤 색이어야하지? 주변의 이미지에서 얻어오자가 IBL의 접근방식이다.

다만, 일부 부분을 위한 이미지라 하여도 조사해야하는 정보량이 많기때문에 시간이 많이 걸리게된다.

 

SH는 미분 방적식과 양자역학의 세계인데...

특정 포인트에서 모든 방향으로 환경광의 정보를 구면좌표계 ( r, θ, Φ )함수들 조합의 계수를 조절해서 표현가능하며,

굳이 IBL 큐브맵에 데이터를 저장하지 않고 계수만 저장하면 된다라는 발상이 SH인 것이다.

제일 상단의 파형을 만들기 위해 단순한 파형들을 더한다.

수학없는 SH 설명

좌 : IBL / 우 : SH

좌:이미지 출처 / https://news.mynavi.jp/article/graphics-66/

 

결국 SH는 구면에서 뭔가 튀어나오거나 들어 간 물체의 형태를 아래처럼 수학적으로 표현하는 것이다.

계수 L이 얼마나 크냐에 따라 좀더 디테일한 모양이 나오는 것이고, 이 함수에 각도같은 것을 넣어 원하는 형태를 얻을 수 있다.

jpg압축의 대략적인 원리와 비슷한데

이미지의 밝고 어두운 픽셀정보를 그래프로 그려 파장형태가 되는데 이를 단순한 파장들로 분해하여 압축 저장한다.

(푸리에 변환)

비슷하게 SH도 특정위치에서 라이트 프로브가 모든 방향에 대해서 Ambient라이트를 어느정도 받아들이는지, 어떤 RGB로 받아야하는지 정보를 들고 있는 것이다.

결국은 기억할 것은 SampleSH함수이다.

ex) half3 ambient = SampleSH(IN.normal); 

SampleSH는 노멀 방향의 Ambient(GI) 컬러 정보를 얻어오는 함수로 라이트 프로브나 스카이 박스로부터 값을 얻어온다.

 

4-2 Blending

 

Legacy에서 URP로 넘어오면서 렌더큐가 Transparent로 반드시 지정되어있어야한다.

'유니티' 카테고리의 다른 글

14강  (0) 2022.06.20
12강 (13주차 진행)  (0) 2022.06.01
11강(12주차진행)  (0) 2022.05.25
10강 (11주차)  (0) 2022.05.18
9강 (10주차)  (0) 2022.05.10
Posted by 텃파