구글링해본 결과 

 

아웃라인그리는 방법은 네가지정도 찾았다.

 

1. 같은메쉬를 한번더 그려서 노말 뒤집은후 조금 부풀린다음 겹치기 (보편적)

 

제일 쉽고 자료가 많지만 메쉬를 한번 더 그리는것과 같은 연산이 들어감.

근데 내가 사용하는방법은 포스트 프로세싱을 사용한 씬 전체에 입히는 후처리방식이고.

이걸쓰면 아웃라인 그릴캐릭터의 매트리얼 인스턴스를 일일이 또 설정해주는 노가다를 해야되서 탈락.

(유니티처럼 매트리얼마다 쉐이더코드 공유하는방법 없나요 ㅠㅠ)

 

2.월드노말맵을 가져와서 좌표값 1씩 오프셋 준다음 외곽선그리기 (Vroid)

 

월드노말맵을 사용한다는말은 캐릭터가 움직일때 노말맵을 계속해서 재연산해줘야해서 

이것도 나름대로 무거워보임.

 

3. 씬뎁스로 외곽선 그리기. (언리얼피셜)

 

구현방식은 2번과 비슷하지만 월드노말맵보다 카메라와 오브젝트간의 거리를 사용하는

흑백으로 출력되는 순수 뎁스값만 사용방법도 괜찮은 방법이지만.

씬뎁스인만큼 카메라에서 거리가 멀어지면 외곽선이 지워지는 문제가 있어서 고민해봅시다.

 

4.윤곽선을 검출하는 sobel알고리즘 사용하기. (지금은 다 까먹은 학식때 배운 영상처리 알고리즘)

 

이게 제일 윤곽선이 깔끔하게 나오지만 제일 무거워보임.

특수한 상황 연출할때빼곤 픽셀연산에 for문을 사용하는건

다른 방식중에 그나마 가벼울때쓰는 매우 특수한경우인데.

뇌피셜로 머리굴려봤을때 이건 추가로 stencil 뎁스값도 써야해서 탈락.

 

 

5.하프램버트 * 그림자색깔.

 

길티기어에서 쓴 방법인데 이것도 간단해서 좋아보입니다.

언리얼 포스트프로세스에서 월드전체에 적용하는거랑 방식이 좀 달라서 어떻게 해야할지 고민중..

 

참고자료.

 

유니티 Vroid 툰쉐이딩 코드(코드저작권때문에 미첨부)

 

이전 포스트 유튜브

 

https://replay.unrealsummit.co.kr/data/usmp2016/pre002.pdf

불러오는 중입니다...

https://www.parallelcube.com/2017/12/02/hlsl-introduction/

 

How to use HLSL and UE4. Introduction – Parallelcube

High Level Shading Language (HLSL) is a programming language that can be used to program modern graphics cards, supports the shader construction with C-like syntax, types, expressions, statements, and functions. UE4 material editor is a good tool to create

www.parallelcube.com

https://blog.felixkate.net/2017/01/19/toon-shading/

 

Overview to “Toon/Cel shading” | FelixK development blog

For the last couple of weeks I often had discussions about toon / anime esque shading. In this post I want to list a few approaches I tried out. Shading Methods Flat shading / Unlit This is not directly shading but it should still be mentioned since this i

blog.felixkate.net

https://m.blog.naver.com/PostView.nhn?blogId=mnpshino&logNo=221541025516&proxyReferer=http%3A%2F%2Fm.facebook.com%2F

 

마둠파님의 블로그!

 

저도 붕괴처럼 해보고싶은데.. 맵 여러개 그려서 표현할만한 내공은 못됩니다 ㅠ

 

붕괴3 방식의 카툰렌더링 구현하기

안녕하세요 마둠파입니다. 간만의 게시글이네요. 한동안 NDC준비하느라고 정신없었고 끝나고나선 여행도...

blog.naver.com

다 만들어보고 프로파일러 돌려보는게 제일 정석이겠지만 시간이 부족하니 뇌피셜 판단으로 끝.

 

 

 

언제 한번 그득하게 언리얼엔진이 어떻게 렌더링하는지 코드분석해보고 싶다.

그전에 다렉을 먼저 봐야한다는 벽부터 부숴야하는데

다른것도 하고싶은게 많고 시간이라는게 너무 유한해서 스텟찍기가 너무 힘들다.

 

월드노말베이스 아웃라인을 만들려고했는데 

 

오늘 안좋은일이 있어서 공부가 손에안잡혔습니다 그래서 그냥 알고있는거를 복습+노가다했습니다.

 

브라우저창에서 임포트한 vroid의 스켈레탈 메쉬창을 열고.

다음과같이 본이름과 본이 표시되도록 설정합니다.

 

두 메쉬의 본을 서로 일치시켜줘야합니다. 

 

vroid는 T포즈지만 언리얼 마네킹은 A포즈네요.

upperArm을 z축으로 45도 내려서 A포즈를 만들어줍니다.

 

그리고 포즈변경  -> 현재포즈 사용을 누릅니다.

 

리타깃 매니저로가서 

다음과같이 

인간형 릭으로 설정 -> 각 본마다 맞는뼈에 매칭시켜줘야합니다 (상당히 노가다)

또한 고급표시로 들어가서 손가락, 트위스트본도 똑같이 매핑시켜준후 

 

제발 꼭 저장을 해줍니다. 나중에 그러면 다른 vroid를 가져와서도 저 매핑파일만 로드해주면 됩니다.

댓글 남겨주시면 매핑파일 보내드리겠습니다.

 

 

자 그리고 마네킹의 애니메이션을 가지고 오고싶으니 리타게팅창을 엽니다.

 

자 그리고 이렇게 하면.

 

 

마네킹의 애니메이션이 제대로 실행되지 않을겁니다.

 

동그라미친것과 같이 본이 전부 뒤틀려있을거에요.

 

원인은 두가지입니다.

 

1.본 매칭이 정확하게 안되어있다.

2.애니메이션을 받는 본이아닌 것까지 다 애니메이션이 들어가버렸다.

 

 

 

 

루트부터 시작해서 여러개의 뼈들이 자식으로 나뉘어져있는것을 볼수있는데.

애니메이션은 캐릭터의 뼈가 기준이고 그것을 움직이므로서 실행됩니다.

 

애니메이션이 필요없는 본들이 애니메이션 때문에 위치가 이리저리 바뀌는것이죠.

 

예를들면 손의 좌표가 애니메이션에 의해 바뀌는데 손만 적용되야할것이 손가락까지 다 들어가버리는겁니다.

 

그러니 뒤틀리는 본들을 다 저렇게 스켈레톤으로 설정해서 부모본의 좌표를 그대로 따라가도록  해줘야합니다.

 

손가락뼈도 다 포함해서요.

 

 

 

 

 

 

 

 

 

 

 

 

잘 된거같긴한데 주먹쥐어야하는데도 엄지손가락이 계속 따봉을 하고있네요 ㅠㅠ

 

 

 

자세히 보니까 vroid의 본과 마네킹의 엄지손가락 본의 개수가 다릅니다 ㅠㅠ 

 

이부분은 맥스로 뜯어다가 손부분만 따로 애니메이션 블렌드 넣어줘서 해결해야겠습니다 

 

 

손꾸락 주먹쥐는건 실패했지만 대략적인 애니메이션은 잘 따라오네요 

 

지금까지 구현한 라이팅은 순수하게 빛을 받는것만 계산하기때문에

 

포인트라이트에 색을 입혀줘도 먹질 않습니다

 

때문에 저는 색깔을 입혀주고 싶었어요 

 

 

주석달았으니 글로 쓰는 것보다  이해하기 쉬울거라 생각합니다.

 

이해안되면 핀만 따로 빼다가 연결해서 하나하나 과정 보시면 됩니다.

 

 

 

RGB 모두 잘 영향을 받는것을 확인할 수있습니다.

 

이정도면 충분히 가볍고 원하는 때깔은 나오는것 같습니다 

 

 

https://www.youtube.com/watch?v=5u-pyWSpoxw&t=30s

 

이것을 참고해서 만들었습니다만 

 

뜯어보니 안에있는 노드 구성이 엄청 복잡하고 필요없는 기능까지 많이들어있어서 무겁습니다.

필요한 기능만 추려서 만들었어요.

 

다행히 노드정리 정말 잘되있어서 분석하는데

오래걸리지 않았습니다 

 

 

 

 

 

 

 

 

 

저같은 이것저것하는거 좋아하는 제너럴리스트는 반반속성이라서 

이런싸움이 안나게 조절가능하는게 없는장점중에 하나인듯합니다ㅜ

(포토샵키기 귀찮아서 그림판으로) 

 

어디 이런 잡부 데려갈 회사 없습니까 ㅠㅠ 

 

제가 덕질하고있는 프린세스커넥트라는 게임의 모션캡쳐

애니메이션(?) 입니다

 

이것처럼 만들려면 어떻게 해야할까 엄청 고민했습니다.

아무래도 만화같은것들은 머리카락에 가려지는 눈썹을 왠만하면 

표시해주는게 더 이쁘거든요.

 

처음에 그냥 뎁스값주고 겹쳐졌을때 lerp로 알파값 적당히 

조절해줘서 섞으면 되겠지 하고 시도했는데 

 

 

 

 

 

 

구현과 삽질의 흔적..

캐릭터 메쉬두개띄우고 겹친다음에

머리메쉬랑 얼굴메쉬를 서로 없애는것부터 시작해서

 

 온갖 삽질을 다해보다가 어찌어찌 비슷하게 만들기는했으나 

캐릭터를 보이는데에만 집중한 콘텐츠 에만 쓸 수 있다는 

사용처가 제한되어있는 것이 단점이었습니다.

 

Z버퍼 뎁스값을 조절해서 통과해보이게 하고싶었으나 

쉬운일이 아니더라구요.

 

 

보통 눈썹은 얼굴메쉬랑  한꺼번에 붙어있도록 모델링되어있고 

얼굴 자체에다가 뎁스값을 넣어버리면 얼굴이 머리카락을

먹어버리는 문제도 있었습니다. 

 

구현은 그냥 저 눈썹 머티리얼만 따로뺴서 뎁스계산을 안한다고 설정해줘서 했습니다 ㅠㅠ 

 

이거는 그냥 구라치는거라 생각하므로 자랑만 하겠습니다 

 

유니티였으면 이런 꼼수 안쓰고 될거같다는 생각이 들었습니다. (하일 유니티드라)

 

 

전 포스팅에서 이야기했던대로 

얼굴 정상으로 돌려주고 시작합니다.

 

보시다싶이 우리가 현실적으로 받는빛은 만화에서 나오는 명암처럼 멋지게 안나옵니다.

더 과장되고 왜곡되야해요.

 

(우선 저 옷의 그림자는 dot으로 구현한것이니 안쓸거니까 지워줍시다.)

 

앞에 포인트 라이트 하나를 얼짱각도에 맞춰서 놔줍니다.

영상하는 친구가 뭐든간에 조명 세개는 써야 이쁘다고 말해줬던것이 생각나네요

대부분 실무에서도 포인트라이트가 아니더라도 저렴한 라이트를 이런식으로 놔줘서 보이게 할겁니다.(뇌피셜)

 

이것만으로는 뭔가 저는 부족합니다.

 

Vroid에서 어떤식으로 쉐이더 코드를 짜줬는지 궁금해서 베껴보기로 했습니다.

 

림라이트 + 저 머리부분은 빛의 영향을 안받도록 이미션맵 해줬네요.

 

요부분을 뜯어봐여.

 

 

rimLighting를 써줬네요 저거 설명 하려면 또 엄청 글 길어지니까 

 

림라이팅에 대해서는 한글로 구글에 쳐보면 좋은자료 많습니다. 

 

이미션은 특별한게 없네요 그냥 노드 짰던거 그대로 두면 됩니다.

 

보니까 lerp하면서 계속 col에다 합쳐주는 형식으로 결과물을 내더라구요. 

 

 

저거 기준으로 함 만들어봅니다.

 

 

다음과 같이 노드를 짜줍니다.

 

림라이트는 프레넬(Fresnel) 공식을 써서 만듭니다. 

 

위에 코드보시면 rimUV라 쓰고 dot연산쓰고 있는거 보이는데..

제가 알고있는 것보다 뭔가 더 복잡하게 림라이트를 구현해놨더라구요.

저거 분석하기 귀찮으니 그냥 잘 알려져있는걸 씁시다.

 

근데 언리얼에서 fresnel을 만들어놨어요! 우와! 킹리얼!

 

저 모델에는 앞머리는 add 뒷머리는 lerp로 한겁니다.

 

add는 그냥 더하는것에비해 lerp는 두개를 입력받아서 사잇값을 출력하는 것이므로 어둡게 나옵니다.

 

add가 더 싸고 이쁘게 나오니까 add 쓰는걸로 결정

 

 

머리카락과 얼굴에 림라이트를 적용한 모습입니다.

 

 

유니티에서 그려지는거하곤 좀 많이 다른모습이지만 

 

저는 제가 만든게 더 맘에듭니다 힣ㅎ

 

 

문득 생각난건데 .

 

눈동자는 빛을 흡수하는게 맞기때문에 다음과같이 노드를 짜서 수정해줍시다.

 

 

before -> after

 

추가로 앞머리 림라이팅이 너무 하얗고 넓어서 떡진머리같으니까 노란색으로 해줍니다.

 

다음포스팅은 저기다가 아웃라인 (외곽선)을 넣어보고 눈썹을 가리는 머리카락을

반투명으로해서 눈썹이 보이도록 해볼까합니다.

 

아웃라인은 같은 메쉬를 두번 그리는 거라 무거워져서 어짜피 안쓸거지만 그냥 공부하는거 정리하는겸 해볼거에요.

 

 

ramp2.TGA
0.00MB

1. 언리얼 에디터상에서 좌측 탭에서 포스트 프로세스 볼륨을 가져옵니다.

 

2. 디테일에서 unbound를 체크해줍니다. (볼륨안에서만 되는것이 아닌 글로벌로 설정하는것입니다.)

 

3.임의의 머테리얼을 만들어서 오른쪽클릭 -> sceneTexture 를 생성하고.

 

 

 

디테일을 다음과같이 설정해줍니다.

 

씬텍스쳐가 뭔지 간단하게 설명하자면

 

현재 화면에 렌더링되고있는 장면 자체를 텍스쳐로 취급하는겁니다.

 

예를들어 씬텍스쳐: 디퓨즈맵이 뭐냐면 

이렇게 빛의 영향을 받는물체의 순수 텍스쳐를 반환합니다.

얼굴은 언릿이니까 까맣게 나오는게 당연하구요.

 

이런겁니다.

 

마스크가 뭐냐면.

 

텍스쳐의 RGB의 한채널의 색상만 출력하겠다는 겁니다. 

 

 

저는 처음볼때 이런생각했습니다 R이면 빨간색은 출력해야되는거 아니야? 했는데.

사실 그런의미가아니라

 

R채널(빨간색)의 채도만큼 흑(0)~백(1)으로 출력하겠다는 겁니다.

그러니 어떤색을 마스킹하던 흑백으로나오는것은 똑같습니다.

 

 

위 이미지는 포스트프로세스 볼륨에 렌더링되고있는 그냥 원래 렌더링텍스쳐와 디퓨즈를 나눈 결과입니다.

 

순수 텍스쳐를 제외하고 그림자만이 저렇게 남게됩니다.

 

그리고 이제 ramp텍스쳐가 필요하니 만들어 봅시다.

 

  포토샵에서 다음과같은 사이즈로 만듭니다.

 

 

이렇게 색상이 나누어진 빼뺴로를 만들어서 언리얼에 드래그해서 임포트합니다.

 

그리고 다음과같이 타일링 설정을 합니다.

 

wrap., clamp , mirror 세개가있는데.

 

저거 뜻이 뭐냐면 저 이미지를 바탕화면으로 설정했을때.

 

이렇게 이미지에 비해 공간이 클시 x축은 어떻게 Y축은 어떻게 하겠냐는겁니다.

 

wrap은 위처럼 그냥 반복해서 타일링해서 채우겠다는 것이고

clamp는 부족한만큼 모짜렐라 치즈마냥 쭈우욱 늘려서 채우겠다는것이며

mirror은 좌우대칭으로 타일링해서 채우겠다는겁니다.

 

그리고 SRGB의 체크를꺼줍니다.

 

 이제 이 램프텍스쳐를 사용합니다.

 

다음과같이 노드를 짭니다.

 

포스트프로세싱0은 0번 볼륨의 렌더링텍스쳐를 가져오고 거기서 디퓨즈컬러를 나누면 

 

렌더링되고있는 씬의 순수 그림자만 남습니다.

 

마스크를 씌운이유는 RGB 3벡터변수말고 하나의 스칼라값을 사용해야하며

 

클램프를 사용하는 이유는 uv는 기본적으로 0~1까지의 좌표를 사용하기때문입니다.

 

입력받은 uv좌표를 기준으로 텍스쳐좌표의 색깔을 그리는데 사용합니다. 

 

사실 저는 처음에 uv좌표에 대해 이해하는게 쉽지가 않았어요 TexCoord에 대해서 알아보고 옵시다.

 

https://cafe.naver.com/unrealenginekr/26327

 

TextureCoordinates를 ...

대한민국 모임의 시작, 네이버 카페

cafe.naver.com

오셀롯님이 작성해주신 글입니다

 

그러면 다음과같이 그려지게되는데.

 

회색부분이 그림자가 드리우는 부분이라고 볼수 있습니다.

 

이대로는 사용하기 어렵죠.

 

그러니까 여기다가 디퓨즈맵을 한번 곱해줍니다.

 

 

이제 뭔가 만화그림자같이 만들어졌죠?

 

저 까만 얼굴 계속보니까 무섭네요.  다음포스팅에서 원래대로 돌리겠습니다ㅎ 

 

다음에는 그림자 들어오는걸 예쁘게 조금더 다듬어주고 빛의방향을 내가 보는 방향으로 바꿔주는 내용에

대해 포스팅 하겠습니다. 

 

GDC에서 발표한 길티기어 툰쉐이딩그냥 한번 봐봐여

https://www.youtube.com/watch?time_continue=1717&v=yhGjCzxJV3E

 

 

dot연산을 이용해 옷에다 적용한 툰쉐도우. (아무튼 그림자임 )

 

원래는 디렉셔널 라이트로해야하지만 

스팟라이트가 보기 쉬우니까 이걸로.

 

콘텐츠브라우저 오른클릭 -> 머테리얼 -> 머레리얼 파라미터 콜렉션 

생성합니다.

 

 

액터에다가 라이팅 할것도아니고  포스트 프로세스 볼륨안에 넣기 귀찮으니 그냥 레벨블루프린트 안에다가 합시다.

 

요로케 빛의 정방향을 얻어옵니다.

 

그리고 원피스 머테리얼 편집.

 

*0.5+0.5는 half lambert라고해서 내적값의 범위가 1,-1 가서 검은색이 넓게 퍼지게되는데.

이것을 1~0까지만 되게 해주는 마법의 공식입니다 

 

dot을 모르겠으면 

 

대마왕님의 블로그에가서 공부해봅시다.

14 15강 보면 있음

https://chulin28ho.tistory.com/81?category=822622

 

ShaderFX를 이용한, 그래픽 디자이너를 위한 기초 쉐이더 강좌 14강

DOT 제대로 알기 14강입니다. 반갑습니다. 흠... 간만에 보니까 막 낯설고 막 이래. 전에 뭔 얘기 했지? 라는 생각에 13강 잠깐 보고 올께요 아... 그거 했구나... 13강때 드디어 Shader의 본질에 접근한 거였군..

chulin28ho.tistory.com

 

수학을 모르겠으면 

https://www.youtube.com/watch?v=P3U9DXFp9SA&list=PL-xqYJ8bjgMC-p94R7iXjFCs-znRg93PJ&index=12

 

원리는 이렇고 

 

문제가 두가지 있읍니다.

 

 

이렇게 라이트벡터가 캐릭터를 안봐서 밤이되거나해서 위를 볼때 

아래에서 비추는 귀신같은 조명이 되어버립니다. 

 

그리고 쉐이더는 dot 연산을 포함한 삼각함수는 나눗셈보다 훨씬 무겁다

+ if문같은 분기문도 중첩되면 무겁다. = 남용하지 말것

 

왜 무겁냐면 컴터가 기본적으로 이진수를 사용하고 나눗셈과 삼각함수의 연산과정을 보면 이해가 될겁니다.

if 분기문또한 내부적으로 빼기연산이지만

초당 30프레임을 렌더링할때마다 1프레임당 최소 몇백 픽셀에 저 연산을 한다고 생각하면.. 음 좀 에바임..

 

게다가 안이쁨.

 

그러니까 다음포스팅에서는 ramp텍스쳐를 활용해 최적화 + 내가원하는 그림자색깔 넣기를 포스팅 하겠습니다.

 

 

이경우는 라이트를 사용하지 않았을때다

 

하지만 언리얼에서 뷰포트모드에서 라이트에서 꺼주고 ini파일을 바뚸준들 shipping 으로 빌드하면 

적용 안되서 이건 아무 쓸모가 없다 히히

 

자 저번 포스트 따라했는데 라이트 포함을 켜면 

 

다이렉트 라이트 영향을 받는 캐릭터가 나올것이다.

 

이제 매트리얼을 더블클릭해서 노드 편집을 해주자.

 

쉐이딩 모델을 언릿으로 하자.

 

그러면 아웃풋 모델에 저렇게 이미시브 컬러만 적용할수있고 나머지 핀은 다 적용이안된다.

 

깜빡하고 안적었는데 곱하기와 더하기의 단축키는 m+왼클 a+ 왼클이다.

 

rbg값으로 설명하자면 0.0.0 은 검은색 111은 흰색이다.

 

어차피 이 글 보는사람은 프로그래머가 아니라고 가정해서 설명한다면.

 

곱하기 연산은 말그대로 저 맵의 rbg값에 노란색 rbg값을 곱해서 혼합시킨다는 개념이고

 

더하기연산은 덮어씌운다는 개념으로 이해하도록 하자.

 

 

 

하면 요로코롬 나온다.

 

근데 먼가 뿌얗다 색감이 안살아요.

 

맨 처음 스샷이랑 너무 차이나자너 

 

왜그렇냐면.

 

언리얼은 라이팅을 정말 대충해줘도 때깔이 정말 좋은이유가 

 

언리얼 내부에서 색 보정해주는 톤매퍼와 포스트 프로세싱이 자동으로 켜져있는게 있다.

 

이것에 대한 연관내용이 숨어있으니 열심히 구글링해서 찾았다.

 

http://api.unrealengine.com/KOR/Engine/Rendering/PostProcessEffects/ColorGrading/

 

컬러 그레이딩 및 필름 톤매퍼

씬 컬러 조절을 위한 톤매핑과 색보정 이펙트입니다.

api.unrealengine.com

 

자세한것은 이 문서를 참고.

 

무튼 언리얼에서 기본으로 적용된 톤맵퍼기능이 언릿계열과 상성이 안맞는 경우가 꽤 있다. 

 

~을 눌러 콘솔창에 

 

라고 입력해주자.

 

 

 

그러면 짠

 

머리카락 떄깔이 돌아왔다.

 

그리고 빛에 영향을 받지않기때문에 

 

포인트 라이트를 가까지줘서 보면 머리카락과 얼굴의 그림자는 안생기고 

 

눈깔과 머머리그림자만 나오는걸 알 수있다.

 

 

딱 여기까지는 내가 혼자 만들고싶었던 Vtuber 쉐이딩이다.

 

Vtuber는 라이팅이 필요없으니 여기까지만해도 내가 원하는 모델링 갖고와서 VR장비와 IK를 통해

 

속은 다리털 아저씨지만 겉은 미소녀로 사기를 칠수있다.

 

 

 

하지만 다음 포스팅에서 조금 더 욕심을 부려서

 

unlit을 그대로 사용하지 않고 

 

쉐이더 연산에저 자주쓰는 dot(벡터의 내적)을 사용해서 

 

빛을 받으면서도 만화같은 명암을 주는 셀쉐이딩에 대해서 포스팅 하겠다. 

+ Recent posts