이펙트란, 영어로 "효과"나 "영향"을 의미하는 말입니다.

 

코믹 일러스트에서는 불꽃이나 번개, 반짝거리는 빛 효과 등을 가리킵니다.

 

이펙트의 종류는 여러가지가 있지만, 이펙트를 사용함으로써 캐릭터가 보다 멋있게, 귀엽게 보이고, 일러스트의 매력이 확 올라갑니다.

 

한 단계 위의 일러스트 표현을 하고 싶을 때는, 꼭 이펙트를 그리는 것에 도전해봅시다!

 

 

 

속성 별 이펙트의 그리는 법과 요령을 해설

 

불꽃 이펙트를 그리는 방법・요령


불꽃의 형태는 타원을 조합하며 밑그림을 그리면 자연스러운 형태가 됩니다.

아웃라인은 곡선으로 그리고, 흔들거리는 선단에서 조금 끊어진 불꽃도 그리면 움직임이 삽니다.

 

 

기본 불꽃 이펙트를 그리는 순서

1. 세로로 긴 타원을 겹쳐서 불꽃의 스케치를 잡습니다. 이때, 불꽃의 밑(중심)부분의 타원을 크게 하고, 끝으로 갈수록 점점 작게 그려가는 것이 요령입니다. 윤곽의 전체는 정중앙을 나눴을 때 좌우가 비대칭이 되도록 합시다.

2. 밑그림을 따라가며 불꽃의 형태를 그려나갑니다. 끝은 뾰족한 형태로, 하늘하늘 부드러운 아웃라인으로 그리도록 합시다. 밑그림 형태 그대로 그리면 딱딱한 인상이 되기 때문에, 군데군데 밑그림에서 삐져나와도 OK입니다.

3. 색을 정할 때는, 불꽃 색의 층을 만듭시다. 붉은 불꽃의 중심부는 밝은 노란색이 됩니다. 불꽃의 끝에 끊어진 불꽃을 그리면 생동감이 삽니다.

 

 

움직임이 있는 불꽃 이펙트를 그리는 순서

1. 타원을 홀쭉하게, 움직이는 방향을 향해서 배치합니다.

2. 타원의 밑그림을 따라서 불꽃의 형태를 그립니다. 이때 불꽃의 흔들거림도 홀쭉하게 그리거나, 끊긴 불꽃 자락도 그려주면 보다 움직임이 느껴지게 됩니다.

 

 

힘 있는 불꽃을 그리는 순서

1. 커다란 타원을 랜덤하게 배치합니다. 타원의 방향은 불꽃의 뿌리 쪽으로 모이는 게 좋겠죠.

2. 타원의 밑그림을 따라서 불꽃의 형태를 그립니다. 폭발하는 듯한 힘 있는 불꽃을 그릴 때는, 불꽃의 흔들거림을 삐쭉삐쭉한 실루엣으로 그리면 힘차게 보입니다.

 

 

https://comic.smiles55.jp/guide/10158/

 

 

번개 이펙트를 그리는 방법・요령


번개는 긴 직선과 짧은 직선을 조합하여 밑그림을 그리면, 날카로우면서 강력한 듯한 번개의 모양이 됩니다.

전체적으로 올곧은 형태가 아닌, 지그재그 실루엣으로 그리면 좋겠죠.

 

 

 

기본 번개 이펙트를 그리는 순서

1. 한 변의 길이가 랜덤한 지그재그를 그립니다.

2. 지그재그에 맞춰서 번개의 형태를 그립니다. 이때, 번개는 같은 굵기로 그리지 말고 각이 지는 곳을 조금 굵게 그리며, 뾰족한 가시도 그려주면 찌직거리는 인상이 생깁니다.

3. 굵은 번개에서 얅은 지그재그 모양의 작은 번개를 갈라져 나오듯이 그리면 자연스러운 형태가 됩니다.

 

또 지그재그의 형태나, 군데군데 작게 파열하는 듯한 전기 덩어리를 그리면 번개의 표현에도 변화를 줄 수 있습니다.

 

 

날카로운 번개 이펙트를 그리는 순서

1. 밑그림의 지그재그를 단순한 형태로 그립니다.

2. 밑그림을 거스르듯 번개의 형태를 그립니다. 강하고 힘있는 번개는 두껍게 그리는 것이 요령입니다.

 

 

빠직거리는 번개 이펙트를 그리는 순서

1. 지그재그로 밑그림을 그리고, 각이 지는 부분에 원을 그려줍니다.

2. 원의 중심에서 방사상으로 가시를 그리면 파열된 듯한 형태가 되어, 빠직거리는 표현이 됩니다.

 

 

 

 

바람 이펙트를 그리는 방법・요령


바람 이펙트는 길고 매끄러운 곡선을 밑그림으로 그려줍니다. 머리카락 다발 같이 선을 겹쳐서 그리면, 질량이 있는 바람의 표현이 가능합니다.

 

 

기본 바람 이펙트를 그리는 순서

1. 일단 바람의 흐름을 밑그림 선을 그려 만듭니다.

2. 밑그림을 따라서 선을 겹치는 듯한 형태로 바람을 그려갑니다. 머리카락 다발처럼 끝이 얇아지도록 그리면 깔끔한 형태가 됩니다. 또, 커브가 강한 부분은 리본처럼 앞뒷면이 바뀌는 것을 의식해서 그려주면 좋겠습니다.

3. 색을 입혀갑니다. 외측보다 내측의 색을 밝게 하고, 뒷면이 보이는 부분은 그림자가 지듯이 살짝 어두운 색으로 주면 입체감이 삽니다.

 

밑그림의 커브가 휘는 정도나 바람의 선을 그리는 방식에 따라, 바람의 세기나 그림의 분위기에 변화를 줄 수 있습니다.

 

 

바람에 강세를 주는 방법

1. 밑그림의 커브가 약하면 바람의 힘이 강해 보입니다. 반대로 넘실거리듯 커브가 강한 밑그림으로 그리면 산들바람과 같이 살랑거리는 바람이 그려집니다.

2. 색을 입혀갑니다. 바람의 선을 그리는 방식이나 색으로 인상이 바뀌기 때문에, 자신이 그리고 싶은 바람의 형태가 되도록 여러가지로 시도해보도록 합시다.

 

 

와풍(일본풍) 바람을 그리는 방식

1.구불구불한 커브가 강한 밑그림을 그려줍니다. 커브가 강한 부분이 각각 비슷한 형태가 되는 게 요령입니다.

2. 색을 입힙니다. 와풍 바람의 표현은 평면적인 게 많기 때문에, 앞뒤의 의식이 없어도 OK입니다.

 

 

 

물 이펙트를 그리는 방법・요령


물의 형태는 양이나 움직임의 빠르기에 따라 크게 바뀝니다. 천천히 움직인은 물은 타원을 조합한 듯한 형태로. 빠르게 움직이는 물은 홀쭉한 타원을 조합하듯 그리고, 바람 이펙트처럼 움직임의 흐름을 만드는 게 좋겠죠.

 

 

기본 물 이펙트를 그리는 순서

1. 바람 이펙트처럼 움직임의 흐름을 선으로 그리고나서, 거기에 맞춰서 타원을 붙여갑니다. 움직임이 빠른 부분을 타원을 길고 홀쭉하게, 움직임이 느린 부분은 타원을 동그라미에 가까운 형태로 그리는 게 요령입니다. 또 물 덩어리를 하나 만들어줌으로서, 이펙트 전체의 움직임에 리듬감이 생기고, 보다 약동감이 늘어납니다.

2. 밑그림을 거스르듯이 물의 흐름을 그려갑니다. 불꽃 이펙트를 그릴 때와 비슷합니다만, 찰랑이는 끝부분은 동그랗게 그리고, 작은 동그라미로 물방울도 뿌려주면 보다 물다운 형태가 그려집니다.

3. 색을 입힙시다. 물도 같은 계열의 색을 여러가지 써서, 명암을 표현하면 입체적이게 됩니다.

 

또 물방울을 흩뿌리는 것뿐만 아니라 물 덩어리를 일부 만듦으로서, 이펙트 전체의 움직임에 리듬감이 생기고, 보다 약진감이 늘어납니다.

 

 

물에 스피드를 주기 위해서는

1.물 밑그림 원의 두꺼움을 바꾸는 것으로 움직임 속도의 차이를 표현할 수 있습니다. 타원의 방향은 바람의 방향이나 움직임의 방향에 맞추어서 정렬합시다.

2. 밑그림을 따라서 물을 그립니다.

 

 

힘 있는 물을 그리는 순서

1. 물의 "덩어리"나, 한 점에서 방사상으로 펼쳐지듯 타원을 배치함으로서 물의 움직임에 강세나 위력이 붙습니다.

2. 밑그림을 따라서 물을 그려갑니다. 군데군데 고리 모양을 그려주거나, 물방울을 많이 그려주면 보다 움직임이 있는 물이 됩니다.

 

좀 더 자세히 물 이펙트를 그리는 법을 알고 싶은 분은 아래의 기사도 추천합니다.

https://comic.smiles55.jp/guide/11541/

 

【水エフェクトの描き方】デジタルで水面・水滴・水泡も簡単キレイに描ける - イラスト・漫

水属性のゲームキャラクターや「海」「雨」をテーマにした絵だと、水しぶきや透明感のある水滴が描きたいですよね。 よりリアルな水エフェクトを描くコツをメイキングで分かりやすく解

comic.smiles55.jp

 

 

 

 

 

연기, 모래 먼지 이펙트를 그리는 방법・요령


연기나 모래 먼지 등 기체의 뭉게뭉게 이펙트는 바람 흐름의 커브와, 여러 형태의 원을 조합하여 밑그림을 만들어 나갑니다.

 

 

기본 연기 이펙트를 그리는 순서

1. 바람의 흐름을 커브로 그리고, 그걸 따라서 연기의 밑그림을 타원으로 그립니다. 타원은 크기도 길이도 제각각으로 그리는 게 요령입니다. 바람의 흐름이 빠른 부분은 타원을 홀쭉하게, 느린 부분은 둥글게 그리는 게 좋겠죠.

2. 밑그림을 따라 뭉게뭉게한 형태로 그립니다. 바람의 흐름이 빠른 부분은 권운과 같이 커브를 써서, 홀쭊한 형태로 그립시다.

3. 색을 넣어갑니다. 광원의 방향을 의식하여, 그림자와 빛을 나눠갑시다.

 

 

흔들흔들 피어오르는 연기 이펙트를 그리려면

1. 피어오르는 연기의 흐름을 곡선으로 그립니다. 이때 뿌리 부분의 커브는 약하게, 위로 올라갈수록 커브를 점점 강하게 주면 좋습니다. 타원으로 형태를 겹치면, 보다 흠들림이 강한 연기가 됩니다.

2. 밑그림을 따라 연기의 줄기를 그립니다. 몇 개인가의 선이 밀집되어 있는 이미지로, 군데군데 흐트러져서 구멍이 생기거나, 끊긴 연기를 그리면 움직임이 삽니다.

 

 

힘 있는 연기 이펙트를 그리는 순서

1. 주위의 환경에 대해서 어디에 바람이 빠르게 흐르고 있고, 어디에 공기가 고여 있는지를 생각하며 바람의 흐름을 밑그림으로 그려가면 움직임이 있는 자연스러운 형태가 됩니다. 바름이 빨리 흐르는 부분은 밑그림을 직선적으로 그리고, 공기가 고이는 부분은 곡선이나 타원으로 그리면 좋겠죠.

2. 밑그림을 따라서 형태를 그려갑니다. 바람이 강한 부분은 거의 직전으로 그려도 괜찮습니다.

 

연기 이펙트는 바람 흐름에 따라 형태가 바뀌기 때문에, 어디에 바람이 강하게 불고 있고, 어디에 공기가 고이는지를 생각하며 그리는 게 요령입니다.

 

 

 

 

빛 이펙트를 그리는 방법・요령


빛 이펙트는 태양이나 전기 등의 발광체, 빛나고 있는 지팡이나 마법진 같이 판타지적인 표현에서도 쓰입니다.

발광체의 중심을 점으로 두고, 그 점에서 방사상으로 선을 그리거나, 똑같은 중심을 두는 원을 발광체의 주변에 그립니다.

이글이글 강하게 빛나고 있는 경우에는, 뾰족뾰족한 선을 많이 그리면 좋겠죠.

또, 발광체는 윤곽선이 보이기 힘들기 때문에, 아웃라인을 밝은 색으로 하면 보다 발광감이 나옵니다.

 

 

 

 

반짝반짝 이펙트를 그리는 방법・요령


반짝반짝 이펙트는 일러스트를 호화스럽게 보이고 싶을 때, 캐릭터의 매력을 올리고 싶을 때 유효합니다.

반짝반짝한 이펙트의 형태에는 여러 패턴이 있습니다.

캐릭터나 세계관에 맞춰서 형태를 그리는게 좋겠죠.

또한, 이펙터의 가시(뾰족거리는) 방향은 전체적으로 통일시키면 자연스럽습니다.

 

 

 

보송보송 이펙트를 그리는 방법・요령


보송보송 이펙트는 로맨틱하고 몽환적인 분위기나 온화한 분위기를 내고 싶을 때 유효한 이펙트입니다.

크기가 다른 발광체 같은 원형을 조합하여 그릴 수 있습니다.

보송보송 이펙트에는 크게 나눠서, 색으로 채운 원형과, 속을 비운 고리 형태의 것이 있습니다.

 

 

 

 

이펙트 배치 방법의 기초와 요령을 해설!

 

그럼 실제로 이펙트를 그리는데 있어, 캐릭터의 어떤 위치에 그리면 되는지, 어떤 실루엣(전체의 형태)로 그리면 되는지를 해설하겠습니다.

 

 

 

동선 타입으로 캐릭터에 움직임을 내자


캐릭터나 사물의 움직임 흐름에 따라 이펙트를 그리는 방법으로, 캐릭터나 사물에 약동감을 내고 싶을 때 효과적입니다.

 

 

 

방사, 집중 타입으로 박력을 내자


한 점에서 방사상, 또는 한 점을 향해 집중되듯이 이펙트를 배치하는 방법입니다.

 

 

만화의 집중선 같은 효과가 있기 때문에 강조하고 싶은 부분에 시선을 유도하는 것이 가능하고, 구도에 박력을 내는데도 유효합니다.

 

 

 

원형 타입으로 다이나믹하게


캐릭터의 주위를 깊이가 있는 원 모양, 또는 소용돌이를 그리듯이 이펙트를 배치하는 방법입니다.

 

 

캐릭터와 이펙트에 앞뒤 느낌이 생기기 때문에, 화면에 깊이가 생깁니다.

 

 

 

 

 

이펙트의 메리트 / 효과를 이해하고 사용하자

 

일러스트의 세계관은 캐릭터의 의상이나 소지품, 배경으로 표현할 수 있습니다만, 이펙트 하나로도 세계관의 표현이 가능합니다.

 

그럼 예시를 보며, 이펙트를 그리면 왜 일러스트의 매력이 올라가는 이유와 이펙트의 메리트를 소개하겠습니다.

 

 

이펙트로 순식간에 세계관이 만들어진다


예를 들어, 평범한 교복을 입고 포즈를 잡은 캐릭터로는 평범한 학원물의 학생으로 보이지만,

손에 불꽃 이펙트를 추가하면 "불꽃 이능력으로 싸우는 학생"으로 캐릭터 이미지가 확 바뀌어,

평범한 학원물에서 "이능력을 가진 인간이 있는 세계"로 세계관이 바뀝니다.

 

 

 

이펙트로 캐릭터에 움직임이 생긴다


또한, 이펙트 하나로 평범한 캐릭터 일러스트에 보다 움직임이 생깁니다.

 

예를 들면 검을 휘두르는 포즈인 캐릭터 일러스트에, 검의 궤도 이펙트를 그림으로서 보다 움직임이 있는 일러스트가 만들어집니다.

 

 

 

정지 포즈에도 이펙트로 약동감이 나온다!


또, 정지하고 있는 포즈에도 이펙트 자체에 움직임을 내면서, 약동적인 그림을 만드는 것도 가능합니다.

 

그저 정지화면 같은 일러스트보다, 움직임이 있는 일러스트 쪽이 박력도 나오고 보기에도 재미 있는 일러스트가 되겠죠.

 

 

 

디지털 기법으로 이펙트를 보다 멋있게

불꽃과 번개, 빛, 반짝반짞 이펙트 등의 발광하고 있는 이펙트는, "글로우 효과"같은 디지털 기법으로 보다 발광감을 더할 수 있습니다.

 

글로우 효과란 이하의 순서처럼, 발광시키고 싶은 것(소재)를 복사해서 색을 바꾸어 겹치고, 그것을 흐릿하게 만든 뒤 합성 모드를 바꾸어 발광감을 내는 효과입니다.

 

그 외에 일러스트의 마무리에 사용되는 효과는 아래의 기사를 참고해봅시다

https://comic.smiles55.jp/guide/8937/

 

イラストは仕上げで差が出る!絵をレベルUPする加工テクニック一覧 - イラスト・漫画(マンガ)

「一通りキャラクターが完成したけど何か物足りない感じがする」「絵が描けたけどいつもと違った雰囲気にしてみたい」と悩んだことはありませんか? イラストの仕上げ加工、またクオリ

comic.smiles55.jp

 

 

 

끝으로

이펙트에는 많은 종류가 있고 각각 그리는 방법이 다르기 때문에, 그리는 게 어렵게 느껴질지도 모릅니다.

하지만 캐릭터 일러스트에 이펙트를 그림으로서, 일러스트의 세계관이 넓어지거나 캐릭터의 움직임이 나오고, 보다 매력적인 일러스트가 됩니다.

 

이펙트도 마스터하여, 한 단계 올라간 일러스트를 그릴 수 있게 되어봅시다!

 

 

 

원글 : https://comic.smiles55.jp/guide/9445/

 

환상정원님 책 보면서 차근차근 따라해보는 중.

어렵긴한데, 수치 몇 개 바꿔주는 걸로 저렇게 바리에이션 양산이 가능하다는 게 신세계다....

예전엔 저거 다 일일이 그리고 있어야 했을텐데...

 

근데 내가 원하는만큼 다룰 줄 알려면 노드들 특성에 대해 아는 것도 아는 거지만

응용할 머리가 있어야 할 듯ㅠ 나중에 이펙트 텍스쳐 제작에 써먹는 게 목표점이긴한데......

여튼 재미는 있다...!

 

회사들 쪽에서도 적극적으로 도입하고 직원들 교육 시키면 제작 시간 단축에 엄청 도움 될 것 같은데

아직은 도입하고 있는 회사가 그렇게까지 많은 것 같지는 않은데 몇 년 이내로 많아질 것 같다...

안쓰기엔....너무 좋은 툴인 듯......

쉐이더그래프에서

평소대로 노드를 짜는데

어쩌다 에러메세지가 뜨는 것을 발견했다.




pow(f, e) will not work for negative f, use abs(f) or conditionally handle negative values if you ex



엥? 이게 뭐여

씬에서는 아무 문제없이 잘 돌아가고 있었다.

네이버에 검색해보니

Pow의 첫번째 인자에 abs를 달아서 사용하라는 말만.


abs 노드가 무슨 역할을 하는지 알아보니 무조건 양수값으로 만들어주는 노드란다.

값이 음수일 경우 -1을 곱해 양수로 만들어주는.


여기저기 물어본 결과

Pow는 음수값을 처리하지 못하니 abs를 달아서 처리해줘라는 에러메세지라는 듯...



근데 일단 씬에선 문제 없이 돌아가기에 그냥 놔두기로 했다(????

포스팅을 쓰는 이유는

나중에 혹여나 문제 생기면 이거 보고 기억하라고......

이번엔 이와 같은 Shader를 만들었기 때문에, 소스를 공개. 해설, 코멘트도 올렸습니다!




원래, 움짤과 같이 파티클이 붕괴하는 것과 같은 연출이 목적이었습니다. 그렇게 때문에, 뚝뚝 아래로 액체가 떨어지는 듯한 베리어 같은 표현으로 했습니다.



참고가 된다면 좋겠군요!




MEMO

-파티클의 감쇠는, 컴포넌트 Aera Effector 2D를 어태치해서 실현하고 있습니다!




소스


Shader "Barrier" { Properties { _Color ("Color", Color) = (1,1,1,1) _DistortionTex ("Disortion Texture(RG)", 2D) = "grey" {} _DistortionPower ("Distortion Power", Range(0, 0.1)) = 0 _width ("Width", Range(0, 0.2)) = 0.05 } SubShader { Tags {"Queue"="Transparent" "RenderType"="Transparent" } GrabPass { "_GrabPassTexture" } Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" //矩形パルス関数 #define pulse(a, b, x) (step((a),(x)) - step((b),(x))) struct appdata { half4 vertex : POSITION; half4 texcoord : TEXCOORD0; }; struct v2f { half4 vertex : SV_POSITION; half2 uv : TEXCOORD0; half4 grabPos : TEXCOORD1; }; sampler2D _DistortionTex; half4 _DistortionTex_ST; sampler2D _GrabPassTexture; half _DistortionPower; fixed4 _Color; float _width; v2f vert (appdata v) { v2f o = (v2f)0; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _DistortionTex); o.grabPos = ComputeGrabScreenPos(o.vertex); return o; } fixed4 frag (v2f i) : SV_Target { half2 uv = i.grabPos.xy / i.grabPos.w; //歪み用テクスチャをuvスクロール float2 uvTmp = i.uv ; uvTmp.y += _Time.x * 2; //rgは0~1の範囲にあるので、-0.5~0.5にずらす half2 distortion = tex2D(_DistortionTex, uvTmp).rg - 0.5; //歪みの強さ distortion *= _DistortionPower; //円外(uv座標内の半径0.5の外)のピクセルは破棄 float dst = distance(float2(0.5, 0.5), i.uv); if (dst > 0.5) discard; //円の内側の半径 float insideRad = 0.5 - _width; //背面の歪み uv += distortion; fixed4 distortColor = tex2D(_GrabPassTexture, uv)* step(dst,insideRad); //円縁 fixed4 circleOutline = _Color * pulse(insideRad,0.5,dst); return distortColor + circleOutline; } ENDCG } }

}





주요 처리의 흐름


STEP.1

-grapPass로 후면을 취득


STEP.2

-노멀맵으로 후면을 왜곡


STEP.3

-원형틀을 추가하여 완성!




STEP.1 : grapPass로 후면을 취득


일단 grapPass로 후면화면을 취득합니다.

관련 소스는 이하에 쓰여있는 대로입니다.


Tags {"Queue"="Transparent" "RenderType"="Transparent" } GrabPass { "_GrabPassTexture" } Pass { sampler2D _GrabPassTexture;


}


GrabPass {}라고 명기하면, 후면 화면을 얻을 수 있습니다. 다만, 주의할 점도 있는데, Tags{"Queue"="Transparent"}라고 할 필요가 있습니다.


불투명한 모든 오브젝트를 그린 후에 후면을 얻어야하기 때문에, "Queue"="Transparent"로 쓰고 있습니다!



그리고 이하의 소스에서는, 후면 화면의 UV좌표를 얻고 있습니다. 사영 공간에서 텍스쳐 좌표로 변환하는 것입니다. "그러한 것"이라고 이해하면 되겠네요 (웃음)


v2f vert (appdata v) { o.grabPos = ComputeGrabScreenPos(o.vertex); } fixed4 frag (v2f i) : SV_Target { half2 uv = i.grabPos.xy / i.grabPos.w;


}



여기서의 해설은 생략하겠지만, 흥미가 있으신 분은 이쪽의 관련 링크를 체크해주세요!


http://edom18.hateblo.jp/entry/2016/11/28/210605

http://asura.iaigiri.com/OpenGL/gl45.html





STEP2 : 노멀맵으로 후면을 왜곡시키자


다음은 노멀맵의 RG요소로 후면을 왜곡시키겠습니다. 매우 심플합니다! 텍스쳐로 왜곡시키는 이미나 구조는, 제가 기재한 Qiita의 기사를 봐주세요!(https://qiita.com/guru_taka/items/c0292fd25b4e739816b6)



초 간단히 설명하자면, 노멀맵의 울퉁불퉁(RG요소)에 의해, UV좌표가 변화합니다.

그 결과, 후면이 왜곡되듯이 비치는 이미지입니다!


그리고는 UV에 스크롤을 줘서, 노멀맵이 아래를 향해 흐르듯이 했습니다. distortion*=_DistortionPower;는 왜곡의 강함을 나타냅니다. 이런 느낌으로 왜곡 강도가 변화합니다.




이번에 사용한 노말맵은 이쪽입니다.




STEP3 : 원테를 추가해서 완성!


마지막으로, 원테를 추가합니다. 흐름은 이런 느낌!


1. UV좌표계에 반경 0.5이외의 픽셀을 전부 파기

2.원테를 단경 펄스 함수로 작성

3.왜곡 후면과 원테를 더하여 완성!



//1. 円外(uv座標内の半径0.5の外)のピクセルは破棄 float dst = distance(float2(0.5, 0.5), i.uv); if (dst > 0.5) discard; //円の内側の半径 float insideRad = 0.5 - _width; //背面の歪み uv += distortion; fixed4 distortColor = tex2D(_GrabPassTexture, uv)* step(dst,insideRad); //2. 円縁 fixed4 circleOutline = _Color * pulse(insideRad,0.5,dst); //3. 背面+円縁

return distortColor + circleOutline;


단경 펄스 함수는 #define pulse(a, b, x) (step((a), (x)) - step((b), (x))로 정의되고 있습니다.




인용:Shader(HLSL), 手続き的にテクスチャ生成など行うとき使用頻度の高い関数




마지막으로


그리고는, 2D Spirte를 작성하여, 적당한 정방형의 Sprite 이미지를 어태치. 그리고, 상기 shader에 따른 머테리얼을 어태치하면 완성입니다!



Blur UI는 좋아합니까


저는 엄청 좋아합니다.



하겠습니다.




방침


묘사중인 화면의 텍스쳐로서 얻을 수 있는 GrabPass를 사용하여, 그 녀석에 가우시안 블러를 얹는 쉐이더를 작성합니다.




가우시안 블러


이미 여러 사이트에도 쓰여 있는 초 메이져한 알고리즘이기 때문에 자세히는 설명하지 않겠습니다만, 요점은 「묘사 대상의 픽셀에 대하여, 그 주변 픽셀의 색을 거리에 따른 가중치를 두면서 평균을 얻는다」라는 것이 됩니다. 그리고 이 가중치에 가우스 함수를 이용하기 때문에 가우시안 블러라고 불리는 겁니다. 이 함수를 쓰는 것으로 아주 좋은 느낌의 흐림 효과를 얻을 수 있습니다.



묘사 부하


가우시안 블러를 우직하게 구현하면 화면상의 각각의 픽셀에 대하여 그 주변의 필셀을 참조하게 되기 때문에, 흐림의 강도를 높이면, 상당한 속도로 계산 부하가 높아집니다. 예를들어 흐림 범위 20X20이라면 각 픽셀에 대하여 20X20=400회의 샘플링이 걸립니다. 그렇게 때문에, 계산 부하를 줄이는 연구가 필요합니다.


일반적으로는 다음과 같은 방법으로 실행합니다. 먼저 전체에 가로 방향만으로만 흐림을 주고, 그 화면에 세로 방향으로 흐림을 겁니다. 이렇게 하는 것으로, 샘플링 횟수는 20 + 20 = 40회까지 줄일 수 있습니다. 참고로 이렇게 해도 같은 화면 결과를 얻을 수 있습니다.


여기서, 2회의 흐림 처리를 어떻게 실행할 건가가 문제가 됩니다. 이 사이트에서는 화면이 아닌 특정 텍스쳐에 대한 가우시안 블러를 거는 방법이 소개되어 있는데, 스크립트에서 수동으로 쉐이더를 불러들일 수 있는 Graphics.Blit을 써서, 가로 방향과 세로 방향의 2회분의 Graphics.Blit을 부르도록 설계되어 있습니다. 하지만 이번과 같이 GrapPass를 쓰는 경우, 그 방법으로는 잘 돌아가지 않습니다. (스크립트를 부르는 타이밍에선 GrapPass가 작동하지 않기 때문. 아무래도 GrapPass는 카메라에서의 화면으로만 기능하는 것 같습니다. 애초에 카메라의 화면 타이밍 이외에서는 "그 시점에 카메라가 묘사한 화면"이 존재하지 않기 때문에 당연하지만요)


그렇기 때문에, GrapPass를 사용한 이상은 의지로라도 스크립트 없이 구현하지 않으면 안됩니다. 그래서 멀티 패스 쉐이더를 쓰ㅃ니다.


멀티 패스 쉐이더라고 해도 대단한 것은 아닙니다. 요는 하나의 쉐이더에 두 개의 처리(pass)를 넣는 것 뿐입니다. 세로 방향의 흐림과 가로 방향의 흐림을 각각 작성하면 됩니다.





먼저는 GrapPass의 아랫부분을 준비


일단은, GrapPass로 화면을 텍스쳐로 얻고 그대로 표시하는 쉐이더를 작성합니다. 블러 쉐이더는 이것을 원형으로 작성해나갑니다.


 Shader "Custom/Blur"

{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
    }
    SubShader
    {

        Tags{ "Queue" = "Transparent" }

        GrabPass
        {   
        }

        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                float4 grabPos : TEXCOORD0;
                float4 pos : SV_POSITION;
                float4 vertColor : COLOR;
            };

            v2f vert(appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.grabPos = ComputeGrabScreenPos(o.pos);
                o.vertColor = v.color;
                return o;
            }

            sampler2D _GrabTexture;

            half4 frag(v2f i) : SV_Target
            {
                half4 col = tex2Dproj(_GrabTexture, i.grabPos);
                return col;
            }
            ENDCG
        }
    }
}





가로 방향의 블러를 작성






파라메터


Properties에 가우시안 블러로 주위 픽셀을 취득하는 반경을 파라메터로서 추가합니다.



 Properties
    {
        _MainTex("Texture", 2D) = "white" {}
        _Blur("Blur", Float) = 10 

    } 




프래그먼트 쉐이더


...(前略)
            sampler2D _GrabTexture;
            fixed4 _GrabTexture_TexelSize;

            float _Blur;

            half4 frag(v2f i) : SV_Target
            {
                float blur = _Blur;
                blur = max(1, blur);

                fixed4 col = (0, 0, 0, 0);
                float weight_total = 0;

                [loop]
                for (float x = -blur; x <= blur; x += 1)
                {
                    float distance_normalized = abs(x / blur);
                    float weight = exp(-0.5 * pow(distance_normalized, 2) * 5.0);
                    weight_total += weight;
                    col += tex2Dproj(_GrabTexture, i.grabPos + float4(x * _GrabTexture_TexelSize.x, 0, 0, 0)) * weight;
                }

                col /= weight_total;
                return col;
            } 

(後略)... 




해설


내용이 많기 때문에 해설합니다.


  [loop]
                for (float x = -blur; x <= blur; x += 1) 

                { 



블러 반경에 따라, 현재 위치를 중심으로 왼쪽에서 오른쪽으로 픽셀을 흐리게 하는 루프입니다.




float distance_normalized = abs(x / blur); 



블러 중심에서의 거리를 구합니다. 0~1의 범위로 정규화하고 있기 때문에, 블러 반경이 변화해도 똑같이 처리할 수 있게 됩니다.



 float weight = exp(-0.5 * pow(distance_normalized, 2) * 5.0); 

                    weight_total += weight; 


가우시안 블러의 알고리즘에 따라 영향력을 계산합니다.





가우시안 블러의 영향력에 사용하는 함수는 이런 느낌의 형태입니다만, y는 완전한 0은 되지 않으므로, 능숙하게 계수를 조정해서 형태를 맞춰야만 합니다. 대체로 블러 반경의 양끝에 영향력이 0.1 이하가 되도록 조정한 결과, 5.0이 걸려 있습니다.

계산한 영향력은 나중에 평균을 얻을 때 사용하기 때문에, weight_total에 가산해둡니다.



  col += tex2Dproj(_GrabTexture, i.grabPos + float4(x * _GrabTexture_TexelSize.x, 0, 0, 0)) * weight; 


정형한 _GrapTexture_TexelSize.xy에는, GrabPass로 얻은 화면의 텍스쳐 사이즈의 역수가 들어갑니다. 이게 그야말로 1픽셀분의 uv공간상의 거리가 되는 겁니다. 그리고는 이것을 원래의 _GrapPass를 참조하여, 영향력을 더해 가산하면 됩니다.


col /= weight_total; 


그리고 가산한 색을 영향력의 합계로 나누면, 영향력을 고려한 평균값이 구해집니다.





세로 방향 블러를 작성하기


세로 방향 블러를 추가합니다. 가로 방향 블러를 더한 결과의 이미지에, 더해서 세로 방향 블러를 더할 필요가 있기 때문에, GrapPass와 Pass를 하나씩 보충해서 써줍니다. Pass의 내용은 거의 가로 방향 블러와 똑같기 때문에 조금 중복 느낌이 있지만, 이렇게 해야만 하기 때문에 포기하고 작성합니다.


...(前略)
                col /= weight_total;
                return col;
            }
            ENDCG
        }

        GrabPass
        {   
        }

        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                float4 grabPos : TEXCOORD0;
                float4 pos : SV_POSITION;
                float4 vertColor : COLOR;
            };

            v2f vert(appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.grabPos = ComputeGrabScreenPos(o.pos);
                o.vertColor = v.color;
                return o;
            }

            sampler2D _GrabTexture;
            fixed4 _GrabTexture_TexelSize;

            float _Blur;

            half4 frag(v2f i) : SV_Target
            {
                float blur = _Blur;
                blur = max(1, blur);

                fixed4 col = (0, 0, 0, 0);
                float weight_total = 0;

                [loop]
                for (float y = -blur; y <= blur; y += 1)
                {
                    float distance_normalized = abs(y / blur);
                    float weight = exp(-0.5 * pow(distance_normalized, 2) * 5.0);
                    weight_total += weight;
                    col += tex2Dproj(_GrabTexture, i.grabPos + float4(0, y * _GrabTexture_TexelSize.y, 0, 0)) * weight;
                }

                col /= weight_total;
                return col;
            }
            ENDCG
        }

    }
}

 


다 하셨나요?







전문


Shader "Custom/Blur"
{
    Properties
    {
        _MainTex("Texture", 2D) = "white" {}
        _Blur("Blur", Float) = 10
    }
    SubShader
    {

        Tags{ "Queue" = "Transparent" }

        GrabPass
        {   
        }

        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                float4 grabPos : TEXCOORD0;
                float4 pos : SV_POSITION;
                float4 vertColor : COLOR;
            };

            v2f vert(appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.grabPos = ComputeGrabScreenPos(o.pos);
                o.vertColor = v.color;
                return o;
            }

            sampler2D _GrabTexture;
            fixed4 _GrabTexture_TexelSize;

            float _Blur;

            half4 frag(v2f i) : SV_Target
            {
                float blur = _Blur;
                blur = max(1, blur);

                fixed4 col = (0, 0, 0, 0);
                float weight_total = 0;

                [loop]
                for (float x = -blur; x <= blur; x += 1)
                {
                    float distance_normalized = abs(x / blur);
                    float weight = exp(-0.5 * pow(distance_normalized, 2) * 5.0);
                    weight_total += weight;
                    col += tex2Dproj(_GrabTexture, i.grabPos + float4(x * _GrabTexture_TexelSize.x, 0, 0, 0)) * weight;
                }

                col /= weight_total;
                return col;
            }
            ENDCG
        }
        GrabPass
        {   
        }

        Pass
        {
            CGPROGRAM

            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"

            struct appdata
            {
                float4 vertex : POSITION;
                float2 uv : TEXCOORD0;
                fixed4 color : COLOR;
            };

            struct v2f
            {
                float4 grabPos : TEXCOORD0;
                float4 pos : SV_POSITION;
                float4 vertColor : COLOR;
            };

            v2f vert(appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.grabPos = ComputeGrabScreenPos(o.pos);
                o.vertColor = v.color;
                return o;
            }

            sampler2D _GrabTexture;
            fixed4 _GrabTexture_TexelSize;

            float _Blur;

            half4 frag(v2f i) : SV_Target
            {
                float blur = _Blur;
                blur = max(1, blur);

                fixed4 col = (0, 0, 0, 0);
                float weight_total = 0;

                [loop]
                for (float y = -blur; y <= blur; y += 1)
                {
                    float distance_normalized = abs(y / blur);
                    float weight = exp(-0.5 * pow(distance_normalized, 2) * 5.0);
                    weight_total += weight;
                    col += tex2Dproj(_GrabTexture, i.grabPos + float4(0, y * _GrabTexture_TexelSize.y, 0, 0)) * weight;
                }

                col /= weight_total;
                return col;
            }
            ENDCG
        }

    } 

} 



주의점


이번의 흐림 처리는 화면 전체가 아닌 특정 영역에만 대해서 실행하고 있기 때문에, 영역의 경계 부분에서 올바른 결과를 얻지 못할 경우도 있습니다. 실용시 유의하시기 바랍니다.



참고


Unityでガウシアンブラーを実装する - e.blog
http://edom18.hateblo.jp/entry/2018/12/30/171214

ShaderLab: GrabPass
https://docs.unity3d.com/ja/current/Manual/SL-GrabPass.html




원문: https://qiita.com/ruccho_vector/items/651f760b3240a253bd1d

유니티로 3D모델을 평범하게 그리면 폴리곤이 표시됩니다. 여기서는 폴리곤의 정점만을 점으로 표현하는 방법을 소개합니다.


정점의 표현 방법을 바꾸는 것만이라면, 무려 2행의 스크립트만으로 끝납니다. 각각의 정점에 여러 색을 입히는 경우에는 쉐이더를 쓰고 있습니다.







토폴리지를 폴리곤에서 포인트로 변경하기


3D모델의 정점 정보는 Mesh에서 관리되고 있어서, 그 정점을 어떤식으로 그릴지는 MeshTopology로 정의되고 있습니다. 통상은 면을 그리기 위해 트라이앵글 토폴로지가 선택되고 있습니다.



MeshTopology에는 다음과 같은 종류가 있습니다.



 토폴로지 명

형태 

 Triangles

삼각형 

 Quads

 사각형

 Lines

 선

 LineStrip

 선분

 Points

 점




여기서는, 정점을 점으로 표시하기 위해서 MeshTopology.Points를 지정합니다. 와이어프레임으로 표시하고 싶은 경우는 MeshTopology.Lines를 선택합니다.









토폴로지를 변경하고 포인트로 표시하기


토폴로지의 변경은, 스크립트에서 간단하게 실행할 수 있습니다. PointController라는 이름의 스크립트를 작성하고, 다음의 내용을 입력해주세요.


using System.Collections; using System.Collections.Generic; using UnityEngine; public class PointController : MonoBehaviour { void Start () { MeshFilter meshFilter = GetComponent<MeshFilter>(); meshFilter.mesh.SetIndices(meshFilter.mesh.GetIndices(0),MeshTopology.Points,0); }

}


여기서는 GetComponent를 사용해서 MeshFilter컴포넌트를 얻고, 메쉬가 가진 정점 정보의 토포로지를 Points로 바꿔서 다시 저장하고 있습니다.


스크립트를 다 입력하셨다면, 작성한 스크립트를 3D모델에 어태치해서 실행시켜봐주세요. 다음과 같이, 정점이 포인트로 나타난 모델이 표시될 겁니다.






정점의 색을 그라데이션으로 표시하기


점마다(정점마다) 색을 바꾸고 싶은 경우에는, 쉐이더를 쓸 필요가 있습니다. 여기서는 위에서부터 아래로 향하는 그라데이션이 되도록 점마다 색을 입히는 쉐이더를 써보도록 하죠.


쉐이더 파일과 대응하는 머테리얼을 생성합니다. 프로젝트 뷰에서 오른쪽 클릭을 하고, [Create] -> [Shader] -> [Unlit Shader]를 선택해주세요. 이름은 Gradation으로 합니다. 그리고, 그 Gradation 쉐이더를 선택한 상태로 [Create->Material]을 선택해서, 대응하는 Custom_Gradation 머테리얼도 작성합니다.




쉐이더에는 다음의 내용을 입력해주세요.



Shader "Custom/Gradation" { Properties { _Color ("Color", Color) = (1, 1, 1, 1) } SubShader { Tags { "RenderType"="Transparent" } Cull Off ZWrite On Blend SrcAlpha OneMinusSrcAlpha Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct v2f { float4 pos : SV_POSITION; float3 worldPos : TEXCOORD0; }; float4 _Color; v2f vert(appdata_base v) { v2f o; float3 n = UnityObjectToWorldNormal(v.normal); o.pos = UnityObjectToClipPos (v.vertex); o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; return o; } half4 frag (v2f i) : COLOR { float4 red = float4(255.0/255,70.0/255,150.0/255,1); float4 blue = float4(90.0/255,90.0/255,250.0/255,1); return lerp(red, blue, i.worldPos.y*0.2); } ENDCG } } FallBack Off

}



여기서는 버텍스 쉐이더로, 처리하고 있는 정점의 월드 좌표를 계산하고 있습니다. 프래그먼트 쉐이더에서는 이 월드 좌표의 y성분에 따라 정점의 색을 결정합니다. 이쁘게 청색에서 홍색으로 그라데이션이 되도록, Lerp메소드로 보간해서 계산합니다.


실행 결과는 다음과 같습니다.








정점을 움직여서 모래가 흩날리는 이펙트


정점을 법선(노말) 방향으로 움직여서 모래가 흩날리는 듯한 이펙트를 만들 수도 있습니다. 버텍스 쉐이더를 다음과 같이 변경해주세요.


v2f vert(appdata_base v) { v2f o; float3 n = UnityObjectToWorldNormal(v.normal); o.pos = UnityObjectToClipPos (v.vertex) + float4(n * _Displacement, 0); o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz; return o;

}



여기서는, 월드좌표계로 법선 정보를 얻고, 그 방향으로 _Displacement 만큼 정점을 바깥쪽으로 움직이고 있습니다. _Displacement는 프로버티 블록에 선언해서, 인스펙터에서 조절할 수 있도록 해놨습니다.









원 출저: http://nn-hokuson.hatenablog.com/entry/2017/06/06/202953


모델링

여전사

2016. 11. 23. 19:26





Goga님 원화를 참고로 제작




▼▼▼▼▼참고원화 주소▼▼▼▼▼

https://www.artstation.com/artwork/lrWBk

'모델링' 카테고리의 다른 글

최강의군단 제임스  (0) 2016.08.18
FF14 이다&파파리모  (0) 2016.08.16
몸통 스컬핑  (0) 2016.08.16






최강의군단 캐릭터 중 하나인 제임스.







아래는 참고 원화



'모델링' 카테고리의 다른 글

여전사  (0) 2016.11.23
FF14 이다&파파리모  (0) 2016.08.16
몸통 스컬핑  (0) 2016.08.16
모델링

FF14 이다&파파리모

2016. 8. 16. 18:09




FF14의 명콤비 이다와 파파리모 '-'

SD풍으로 만들어 보았다

ㅍ..파파리모는 원래부터가 쪼꼬미라 사이즈적으론 큰 차이는 없지만 ㅋㅋㅋㅋㅋ

'모델링' 카테고리의 다른 글

여전사  (0) 2016.11.23
최강의군단 제임스  (0) 2016.08.18
몸통 스컬핑  (0) 2016.08.16
모델링

몸통 스컬핑

2016. 8. 16. 18:05




스컬핑 연습삼아 만들어 본 것.

'모델링' 카테고리의 다른 글

여전사  (0) 2016.11.23
최강의군단 제임스  (0) 2016.08.18
FF14 이다&파파리모  (0) 2016.08.16
1