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

애니메이션(?) 입니다

 

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

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

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

 

처음에 그냥 뎁스값주고 겹쳐졌을때 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

 

Const &char Class::Method (int* pt)

 

해당 메소드의 반환값(char)을 상수화시켜서 못바꾸게 하겠다는뜻.

 

이걸 그대로 받아서 변수로쓰면 못바꿈.

 

&char Class::Method (int* pt) Const

 

메소드 자체를 상수화 하겠다는뜻.

 

메모리스택에서 얘가 다 돌고 해제될때까지 

 

내부 데이터들이 다 상수화되서 안바뀜. 

 

스레드,동시성 프로그래밍할떄 유용할거같다.

 

&char Class::Method (Const int* pt) 

 

pt라는 포인터가 가리키는 매개변수의 주소값을 상수화시켜버리는것.

 

어디가리키는지는 못바꾸는데 가리키는곳의 데이터는 바꿀 수있다.

 

 

&char Class::Method (int* Const pt) 

 

pt라는 포인터가 가리키는 매개변수의 데이터를 상수화 시켜버림.

 

포인터가 가리키는 주소는 바꿀수있는데 데이터를 못바꿈

 

 

규칙성을 따져보면

const는 앞에 뭔가 있으면 그거 하나를 얼려버림.

그리고 앞에 아무것도 없고 뒤에 뭔가 있으면 그걸 다 얼려버림.

 

const를 어떻게 넣냐에 따라서 

프로그래머가 원치않게 변수조작하는것을 미연에 방지해줄수 있음

https://devblogs.nvidia.com/introduction-turing-mesh-shaders/

 

Introduction to Turing Mesh Shaders | NVIDIA Developer Blog

Turing introduces a new programmable geometric shading pipeline, mesh shaders,, enabling threads to cooperatively generate compact meshes on the chip.

devblogs.nvidia.com

영알못+그알못이라 개념만 이해한대로 보면.

 

 

지금까지 렌더링 파이프라인은

 

프레임마다

인접한 버텍스끼리 그거 다 연결해버리고 테셀레이션해서 나누고 굴곡준다음에

지오메트리로 다시 단위로 나눌때 거기서 중복되서 필요없는 정점들 지워서 최적화하는 방식으로

폴리곤 렌더링을하고 래스터라이징을 했다면

 

이제는 이거 안에 필요없는연산 너무 꾸역꾸역넣어서 느리고

넘 꾸진거같으니 이전 버텍스의 사용했던 중복되는 버텍스의 인덱스를 치환해서 재계산을 안하고

바로 병렬처리해서 빠르게 렌더링하겠다는 소리같은데.

 

 

 

그림보니까 파이프라인 자체가 바뀌어있다. 그아래 뭐 원리 설명하는 그림 있느거 같은데 아직 이해가안대고..

 

이거이러면 그래픽플머님들이랑 게임엔진회사들 난리날거같다.

 

외계인형님들이 나같은 빡머갈들을 위해 쓰기 쉬운 API 새로 설계해서 만들어주실거고

 

이전에쓰던 다렉이랑 오픈지엘은 옛날겜에만 쓸거고 

 

앞으로 무선디바이스 요구하는 VR이나 홀로렌즈, 더 그래픽쩌는 모바일게임성능을 내는데 쓰일건데

 

님들 갓겜 만들고싶으면 이전까지 공부한거 갖다버리고 우리가 만든거 새로공부하세요 ^^*

 

아 너무 무섭다.

 

저번처럼 바인딩할 버튼을 만들고 

인터페이스에 가상함수를 만들고.

 

 

상속받은 인터페이스를 가져오고.

 

 

 

인터페이스 기능을 구현. (핵심)

 

 

 

메뉴에서 인터페이스의 함수를 호출할 함수를 작성 .

그리고 버튼이벤트 바인딩.

 

 

 

 

 

 

 

UMG와 부모위젯헤더파일에 이렇게 바인딩시킨후.

 

클릭했을떄 함수 등록

 

마지막줄의 인터페이스함수를 호출하는 형식으로 동작하는데 구성은 이렇다.

인터페이스 선언 -> 인스턴스에서 다중상속 -> 구현  ->

메인메뉴에서 여기서 구현한 인터페이스를 받아서 호출함. 

 

결과

 

 

 

아직도 몇달째 고민하고있는 문제다.

 

내가 프로그래밍을 시작한 계기는 게임만드는게 재밌어서였고.

 

물론 아예 대기업처럼 밑바닥부터 진행을 할것이면 디자이너와 TA도필요하지만.

 

모델링 에셋은 왠만하면 돈으로 구매할수있어 커버가 가능하고 거기서 조금조금씩 내가원하는스타일로 바꾸는것은

어렵지않게 가능하다.

 

하지만 프로그래밍은 돈으로 살수가 없다. 만약 외주를 구했다쳐도

수정이고 업데이트고 필요할때 그사람을 계속불러야하고 내가 맘대로 고쳤다간 터지는일이 발생할것이

불보듯 훤하기때문에 결국 코딩은 직접하는것이 고통을 감내하면서도 심적으로 편안하기때문에.

프로그래밍을 메인으로 공부하는것.

 

나는 이미 만들어져있는 툴이나 엔진을 활용하면 빠른시간내에 최적의 결과물을 낼수있고 그걸로 벌수있으면 

그게 최선이고 제일 효율적이라 생각한다.

 

예로들어 내가 학부시절에 완전 쌩 하드코딩으로 허접한 FPS를 만들었었는데.

유니티 엔진에서 이미 쓰라고 만든 스탠다드에셋이 있었고 그게 더 성능이 좋았을때만큼

허탈감오고 화나는일이 없었다.

 

아주 도움이 안된 경험은 아니지만. 쪽팔려서 포트폴리오로 쓰지않았다.

 

또, 3Dmax로 6개월동안 개고생하며 내가 만들고싶은 캐릭터 만들었는데 vroid가 그걸 다 씹어먹어버렸다.

 

나는 내가 원하는 게임만들고싶어서 프로그래밍 공부한것이며.

 

공부 열심히해서 고연봉 프로그래머로 인생 성공할거야! 라고 시작한것이 아니어서.

 

프로그래머와 개발자사이의 진로에서 아직 명확한 이정표를 못 꽂고있다.

 

항상 내가 의문을 느끼는게 한국의 네임드 프로그래머들이 왜 퇴직후 치킨집 고기집일까 싶다.

 

프로그래머는 진짜 공부만하면 웬만한거 다 만들 수있다고 생각하는데. 

 

고객 니즈 파악을 못해서 돈되는걸 못 만드는건가 싶은건가 생각이 들기도하고 오만가지 생각이 든다.

 

대기업 회사가 원하는 인재상을 보면

 

특화된 프로그래머를 원한다.

포트폴리오보다. 수학,자료구조,알고리즘,그래픽스 기초지식을 물어본다.

당연히 중요하다. 기초.  맞는말이다.

지원자도 많기 때문에 이를 한명한명 또 보기 어려워서 수백명의 지원자를 가려내기위해 코딩테스트가 필요한것이다.

그리고 지금의 대기업들은 피쳐폰시절부터 화면에 도트찍으면서 이루어낸 명성인만큼 로우레벨울 중요시한다.

내가 사장이어도 나보다 코딩 잘하는애 뽑아다 쓸거다.

 

근데 이것들을 시험치려고 공부하면 졸업하고서 3개월에서 길게는 1년 배웠던걸 달달 외워서 복습해야한다. 

솔직히 배웠던건 개념만 남아있지 디테일한건 안쓰면 다 까먹어서 시험볼때 끄내쓰기가 어렵다.

대기업 공채시험합격하는사람들은 정말 대단한거같다.

 

난 왠만한건 다 만들 수 있다고 생각하지만,

나보다 빨리 배우는 천재들을 주변에서 많이 봤기때문에 머리는 좋지않다고 생각한다. 

구현이 필요할때 이런게 있었지! 하면서 빼다가 다시 공부해서 쓰는게 보통이라고 난 생각한다.

 

솔직히 말해서 갑자기 양방향 링크드리스트로 큐 손코딩하라 그러면 못한다.

대충 흉내야 낼수는있겠지만 분명 안돌아가는 코드일것이다ㅠ.

#include <queue> 쓰고 나올거같다. 

 

여기저기 구글링하다보니

대기업 합격률을 자랑하며 코딩인터뷰 대용으로 알고리즘만 따로 가르치는 학원도있길래 헛웃음만 나왔다.

대기업 취직을 인생목표로해서 알고리즘 고시공부를 또 하라는건 좀 아니라 생각했다.

취직해서 뭐 회사에서 시키는거 하는게 인생의 장래희망이라 하기엔.. 절레절레.. 

 

내 성격에는 그렇게 공부하면 지식을 제대로 흡수하지 못했다.

 

나쁜말로 프로그래밍에 집중 안하고 딴짓하면서  합리화했다고 들어도 나는 수긍할수밖에 없다.

이 고민을 교수님이나 청강대 교수님을 포함해 꽤 여러분께 털어놨는데.

프로그래머가 되고샆냐. 크리에이터가 되고싶냐 라는 말이 되돌아왔다.

 

나는 모니터에서 0과 1이 바뀌는것보다 뭔가 더 크게 변하는것을 좋아한다고 생각하기때문에,

조금 고민하다가 크리에이터라고 대답했었고 지금도 그렇다고 생각한다.

 

그러자 교수님은 나는 한 방향에 특화되어있어서 모르는 지식은 도와줄수있지만

너에게 가르쳐 줄 수있는것이 별로없다. 라고 하셨다.

 

그래서 지금은 그냥 지금 내가 좋아하는것을 열심히 추진하면 뭔가 기회가 딱 오지 않을까 싶어서.

그냥 마음가는걸 열심히 하자 생각했다.

+ Recent posts