블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2738)
Unity3D (817)
Programming (475)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (58)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (53)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
04-30 00:00

유니티 – 그래픽 성능 최적화

원문 - http://docs.unity3d.com/Documentation/Manual/OptimizingGraphicsPerformance.html

자주 보는 문서라 한글로 보는 게 편할 것 같아 번역해서 적어놓습니다. 오역이 있을 수 있습니다. T_T

 

2012년 7월 29일 자 버전 번역본

 

그래픽 성능 최적화

대다수 게임의 성공에 있어 좋은 성능은 가장 중요한 부분입니다. 아래 내용은 여러분 게임의 그래픽 렌더링 속도를 최대화하는 몇 가지 요약 지침입니다.

 

그래픽 비용이 어디서 많이 드는가

여러분 게임의 시각적 부분은 컴퓨터의 두 장치 GPU나 CPU에서 주로 비용을 사용합니다. 무슨 최적화든지 간에 첫 번째로 볼 것은 성능 문제가 있는 곳을 찾는 것입니다. 왜 그러냐 하면 GPU와 CPU의 최적화 방법은 상당한 차이(도 있고 반대로 GPU일 때도 그렇지만, CPU를 최적화하는 동안 GPU를 좀 더 일하게 하는 일이 상당히 흔하기)가 있기 때문입니다.

 

발생 빈도가 높은 병목과 그를 확인하는 방법

 

- GPU는 보통 fillrate나 메모리 대역폭에 의해 제약을 받습니다.

- 게임을 저해상도로 돌리면 더 빨라진다고요? 그렇다면, 아마도 GPU상의 fillrate에 의해 제약받고 있을 겁니다.

- CPU는 보통 draw calls라고 부르는 렌더링을 해야 하는 물체 수에 의해 제약을 받습니다.

렌더링 통계 창에 나오는 draw calls를 확인해 보세요. 이게 몇천(PC에서)이나 몇백(모바일에서)을 넘는다면 물체 수를 최적화해야 합니다.

 

물론, 이건 보통 이렇다는 겁니다. 병목은 다른 곳에 있을 수도 있습니다. 발생 빈도가 낮은 병목은 다음과 같습니다.

 

- GPU와 CPU 둘 다 확인해도 렌더링이 문제가 아닌 경우! 예를 들어, 직접 작성한 스크립트나 물리가 실제 문제를 일으키고 있을 수 있습니다. 분석기를 사용해 문제를 찾아보세요. (하지만 난 베이직이지.)

- GPU가 처리할 정점이 너무 많은 경우. 얼마나 많은 수의 정점이 “괜찮은지”는 GPU와 정점 셰이더의 복잡도에 의해 좌우됩니다. 모바일에서는 “십만 개를 넘지 않고”, PC에서는 “몇백만 개를 넘지 않는 것”이 적당합니다.

- CPU에서 처리하는 정점이 처리하기엔 너무 많은 경우. 골격 메시(skinned meshes), 피복 시뮬레이션, 입자(particle) 등이 될 수 있습니다.

 

CPU 최적화 – draw call 수

어떤 물체를 화면에 표현하기 위해 어느 조명이 물체에 영향을 주는지 알아내기, 셰이더와 셰이더 매개변수를 설정하기, 그리기 입력을 그래픽 드라이버로 보내기, 그래픽 카드로 보낼 명령을 준비하기 같은 몇 가지 작업을 CPU가 합니다. “물체당 한 번씩”하는 앞에 나온 모든 CPU 작업은 그렇게 많이 저렴하지 않기 때문에 보이는 물체가 많다면 비용이 증가할 것입니다.

 

예를 들어서, 삼각형(보통 국내에서는 폴리곤이라고 부르는데 원문 그대로 번역합니다.) 천 개를 가지고 있다고 합시다. 삼각형 하나로 구성된 천 개의 개별적인 메시가 있을 때보다 모든 삼각형이 한 개의 메시 안에(로 구성되어) 있을 때가 비용이 더 많이 많이 저렴할 겁니다. GPU상에서 두 경우의 비용은 아주 비슷하지만, CPU에서 천 개의 물체를 표현 완료하는 것은(한 개에 비해) 비용이 상당할 것입니다.

 

CPU가 일을 더 적게 하도록 보이는 물체 수를 줄이는 것이 좋습니다.

 

- 근접해 있는 물체들을 유니티의 draw call 일괄처리를 사용하거나 직접 합칩니다.

- 개별 텍스처를 큰 텍스처 지도(texture atlas)에 넣거나 다른 방법으로 물체의 재질(materials)을 적게 사용합니다.

- 물체를 여러 번 렌더하게 하는 기능을 적게 사용합니다. (반사, 그림자, 픽셀당 조명 등등, 아래 참조.)

 

각각의 메시가 최소 몇백 개의 삼각형을 갖도록 물체들을 함께 합치고 합친 메시당 한 개의 재질만 사용합니다. 재질을 공유하지 않는 두 물체를 합치는 것은 성능 향상이 전혀 없다는 것을 이해하는 것이 중요합니다. 두 메시가 같은 텍스처를 사용하지 않는 것이 다중 재질을 사용하는 가장 흔한 이유이기 때문에 CPU를 최적화하려면, 반드시 합치려는 물체가 같은 텍스처를 사용하게 해야 합니다.

 

하지만 전방 렌더링 패스에서 픽셀 조명을 많이 사용하면 아래에 설명한 대로 물체 결합을 할 수 없는 상황이 생길 수 있습니다.

 

GPU: 모델의 지오메트리 최적화

모델의 지오메트리(기하 구조, 외형, 외견, 폴리곤)를 최적화하려면 기본적으로 두 가지 해야 할 것이 있습니다.

 

- 필요하지 않은 경우 삼각형을 더 사용하지 말 것

- UV 매핑 이음새(재봉선, uv가 분리되어 버텍스를 공유하지 못하기 때문에 처리해야 할 데이터가 늘어납니다.)와 심한 모서리(겹쳐있는 정점) 수를 가능한 한 적게 유지하도록 노력할 것

 

그래픽 하드웨어에서 처리하는 실제 정점 수는 삼차원 모델링 프로그램에서 알려주는 수와 대개 같지 않다는 것을 주목하세요. 모델링 프로그램은 보통 기하학적 정점 수, 즉 모델을 구성하는 꼭짓점 수를 표시합니다. 하지만 그래픽 카드는 렌더링을 위해 어떤 기하학적 정점을 두 개나 그 이상의 실제 정점으로 분리해야 할 때가 있습니다. 정점이 다중 법선, 다중 UV 좌표나 다중 정점 색상을 가지고 있다면 반드시 분리해야 합니다. 그 결과 유니티에서 표시되는 정점 수는 언제나 삼차원 프로그램이 알려주는 것보다 많습니다.

 

모델의 지오메트리 양은 GPU와 관련이 가장 많지만, CPU에서 모델을 처리하는 메시 스키닝과 같은 유니티의 몇몇 기능도 관련이 있습니다.

 

조명 성능

전혀 계산하지 않는 조명이 항상 가장 빠릅니다! (당연한 거 아닌가?!) 프레임마다 계산하는 대신 정적 조명을 딱 한 번 “굽는” 라이트맵을 사용해보세요. 유니티에서는 단순히 장면(scene) 안에 조명을 설치하는 것보다 라이트맵이 적용된 주변 환경(지형, 배경 등)을 생성하는 과정이 살짝 할 게 더 많지만,

 

- 이렇게 하면 더 많이 빨라집니다. (픽셀당 조명 2개의 경우 2~3배 정도)

- 전역 조명을 구울 수 있고 라이트매퍼가 결과물을 부드럽게 할 수 있으므로 시각적으로 더 많이 좋아집니다.

 

대개 곳곳에 조명을 더 추가하는 대신 셰이더와 콘텐츠로 간단하게 속임수가 가능합니다. 예를 들어 “뒷조명(rim lighting, 역광)” 효과를 얻기 위해 카메라 쪽을 곧게 비추는 조명을 추가하는 대신 전용 “뒷조명” 계산을 셰이더를 안에 직접 추가하는 방법을 고려해보세요.

 

전방 렌더링의 조명

픽셀당 동적 조명은 영향을 받는 모든 픽셀에 큰(significant) 렌더링 부담(overhead)를 추가로 주고 물체들을 다중 패스 렌더링을 하게 합니다. 모바일과 최저사양 PC의 GPU처럼 사양이 낮은 기기에서는 한 개의 물체에 하나 보다 많은 픽셀 조명이 비추는 것을 피하고, 정적 물체를 밝히기 위해 조명 계산을 모든 프레임마다 하는 대신 라이트맵을 사용해보세요. 정점당 동적 조명은 정점 변형 시 큰 비용이 추가될 수 있습니다. 어떤 물체든지 여러 조명이 비추는 상황을 피하려고 노력하세요.

 

만약 픽셀 조명을 사용하고 있다면 각각의 메시는 픽셀 조명이 메시를 비추는 만큼 여러 번 렌더링 될 것입니다. 아주 멀리 떨어진 두 메시를 합쳤다면 합쳐진 물체의 영향을 받는 크기는 증가할 것입니다. 이 합쳐진 물체를 비추는 모든 픽셀 조명은 렌더링 중 (조명 빛이 닿지 않는 멀리 떨어진 부분도) 계산에 들어가기 때문에 렌더링해야 할 렌더링 패스 수가 증가할 것입니다. 일반적으로 합쳐진 물체를 반드시 렌더해야 되는 패스 수는 (합치게 될) 각 개별적 물체의 패스 수의 합이기 때문에 물체를 합쳐서 추가되는 것은 없습니다. 이런 이유로 다른 위치에 있는 픽셀 조명의 영향을 받게 될 너무 멀리 떨어진 메시들을 합쳐서는 안 됩니다.

 

렌더링 중, 유니티는 메시를 둘러쌓고 있는 모든 조명을 찾고 이중 가장 영향을 주는 조명을 계산합니다. 얼마나 많은 조명이 픽셀 조명과 정점 조명이 될 건지 조정할 때 품질 설정을 사용합니다. 각각의 조명은 메시로부터 얼마나 멀리 떨어져 있는지에 기반을 둔 중요도와 빛이 얼마나 강할지를 계산합니다. 그뿐만 아니라 몇몇 조명은 순전히 게임 맥락(개발자의 의도)에 따라 다른 조명보다 더욱 중요하므로 모든 조명은 Important또는 Not Important를 설정할 수 있는 표현 방법(Render Mode) 설정을 가지고 있고 조명이 Not Important로 설정된 조명은 일반적으로 낮은 간접 처리를 하게(갖게) 됩니다.

 

예를 들어, 플레이어의 자동차가 전조등을 켜고 어둠 속에서 달리고 있는 자동차 게임을 생각해보세요. 전조등은 게임에서 시각적으로 가장 중요한 조명이기 때문에 표현 방법을 아마도 Important로 설정할 것입니다. 반면에 게임의 (다른 자동차의 후면등 같은) 다른 조명들은 덜 중요하고 픽셀 조명의 시각 효과 향상이 없을 것입니다. 이런 조명들이 작은 이익을 줄 수 있는 곳에서 렌더링 비용이 버려지는 것을 피하고자 렌더 모드를 안전하게 Not Important로 설정할 수 있습니다.

 

픽셀당 조명 최적화는 CPU와 GPU 양쪽 모두 자원을 절약하게 합니다. CPU는 draw call이 적게끔 하고 GPU는 처리할 정점이 적게끔 하며 이 모든 추가적인 렌더링의 레스터라이즈될 픽셀을 적게 만듭니다.

 

GPU: 텍스처 압축과 밉 맵

압축된 텍스처를 사용하면 텍스처의 크기를 줄일 수(그 결과 로딩 시간이 더 짧아지고 메모리가 차지하는 공간이 더욱 작아집니다.) 있고 렌더링 성능을 극적으로 올릴 수 있습니다. 압축된 텍스처는 압축되지 않은 32bit RGBA 텍스처가 필요로 하는 메모리 대역폭의 일부만 사용됩니다.

 

텍스처 밉 맵 사용하기

(mipmaps 또는 MIP maps, 앞에 있는 MIP는 라틴어 multum in parvo에서 온 말로 작으면서 효율적(much in little)이라는 뜻이 있다네요…그렇다고요 ;ㅁ;)

경험상 말하자면, 삼차원 장면에서 사용되는 텍스처는 밉 맵 생성하기(Generate Mip Maps)를 항상 켜두세요. 같은 식으로 텍스처 압축도 적용하면 GPU가 렌더링 중일 때 전송되는 텍스처 데이터양을 제한하는 데 도움이 됩니다. 밉 맵이 적용된 텍스처는 GPU가 작은 삼각형에 저해상도 텍스처에 사용할 수 있게 합니다.

 

위 내용의 한 가지 예외는 텍셀(텍스처 픽셀)이 2D 게임상이나 UI 요소로써 화면 픽셀에 1:1로 적용되어 렌더할 때입니다.

 

LOD와 레이더당 배제 거리

몇몇 게임에서는 CPU와 GPU가 사용되는 것을 줄이기 위해 큰 것보다 작은 물체를 더욱 공격적으로 배제(cull)하는 것이 적절할 수 있습니다. 예를 들어서 먼 거리에서 큰 건물이 아직 보일 때 작은 돌과 파편은 (화면 픽셀보다 작아져서) 보이지 않을 수 있습니다.

 

위 내용은 Level Of Detail 기능(하지만 난 베이직이지.)을 사용하거나 카메라의 레이어당 배제 거리를 직접 설정해서 적용 할 수 있습니다. 작은 물체를 개별 레이어에 넣고 Camera.layerCullDistances 스크립트 함수를 사용해서 레이어당 배제 거리를 설정할 수 있습니다.

 

실시간 그림자

실시간 그림자는 멋지긴 하지만 CPU에는 draw calls를 추가하고 GPU에는 추가 처리를 하게 하여 성능에 상당한 비용이 들게 합니다. 더 상세한 내용은 그림자 항목을 보세요.

 

GPU: 높은 성능의 셰이더 작성법

최고사양 PC의 GPU와 최저사양 모바일 GPU는 성능이 말 그대로 수백 배 차이가 날 수 있습니다. 단일 플랫폼에서도 마찬가지입니다. PC 상에서 빠른 GPU는 느린 통합형 GPU보다 수십 배 빠르고 모바일 플랫폼에서도 똑같이 GPU 간에 큰 차이를 볼 수 있습니다.

 

그러므로 모바일 플랫폼과 최저사양 PC의 GPU 성능은 여러분이 개발하고 있는 장비보다 매우 낮을 거란 것을 기억해야 합니다. 보통 셰이더는 좋은 성능을 얻기 위해 계산과 텍스처 읽기를 줄여 손수 최적화해야 합니다. 예를 들어 몇몇 내장(built-in) 유니티 셰이더는 더 빠른(지만 어떤 제약을 받거나 비슷한 효과를 사용하기 때문에 더 빠른) “모바일” 대용 셰이더를 갖고 있습니다.

 

아래 내용은 모바일과 최저사양 PC의 그래픽 카드에 가장 중요한 몇 가지 지침입니다.

 

복잡한 수학적 연산

수학의 (pow, exp, log, cos, sin, tan, 등등 같은) 초월함수는 비용이 상당하기 때문에 경험상 볼 때 저런 픽셀당 연산은 하나를 넘으면 안 됩니다. 하나를 넘었다면 대용으로 룩업 텍스처를 사용하는 것을 고려해 보세요.

 

어떻게 하든 간에 직접 normalizedotinversesqrt 연산을 작성하려는 것은 권장하지 않습니다. 내장 함수를 사용하면 드라이버가 더 나은 코드를 만들어 낼 것입니다.

 

알파를 테스트하는(버리는) 연산은 프라그먼트(픽셀) 셰이더를 느리게 만든다는 것을 기억하세요.

 

부동 소수점 연산

직접 셰이더를 작성할 경우 부동 소수점 변수의 정밀도(precision)를 반드시 적어야 합니다. 최상의 성능을 얻기 위해 가능한 낮은 정밀도의 부동 소수점 형식을 고르는 것은 중요합니다. 연산의 정밀도는 대게 데스크톱 GPU에서는 완전히 무시되지만, 대부분의 모바일 GPU 상에서의 성능에 있어서는 중요합니다.

 

셰이더가 Cg/HLSL로 작성되어 있다면 정밀도는 다음과 같이 명시되어 있습니다.

 

float : 32-bit를 전부 사용하는 부동 소수점 형식으로 정점 변형에 적합하지만, 성능에 있어 가장 느립니다.

half : 16-bit로 줄인 부동 소수점 형식으로 텍스처 UV 좌표에 적합하고 대략 float보다 두 배정도 빠릅니다.

fixed : 10-bit 부동 소수점 형식으로 색상, 조명 계산과 다른 고비용 연산에 적합하며 대략 float보다 네 배정도 빠릅니다.

 

셰이더가 GLSL ES로 작성되어 있다면 부동 소수점 정밀도는 각각 highpmediumplowp로 명시되어 있습니다.

 

셰이더 성능에 대해 더 자세한 내용은 셰이더 성능 항목을 읽어보세요.

 

게임을 더욱 빠르게 만들기 위한 요약 확인 항목

- PC 게임을 만들고 있다면 목표로 하고 있는 GPU에 맞춰 정점 수를 프레임당 2십만에서 3백만 아래로 유지하세요.

- 내장 셰이더를 사용하고 있다면 모바일이나 Unlit 범주에 있는 것을 고르세요. 이 셰이더들은 기존 복잡한 셰이더를 간략화하고 비슷한 효과를 내게 만든 형태로써 모바일이 아닌 플랫폼에서도 잘 동작합니다.

- 장면 하나당 재질 종류 수를 적게 유지하세요. 다른 물체끼리 재질을 가능한 한 많이 공유하세요.

- 움직이지 않는 물체에 Static 속성을 적용해서 Static batching 같은 내부 최적화를 할 수 있게 하세요. (하지만 난 베이직이지.)

- 필요하지 않다면 픽셀 조명을 사용하지 말고 지오메트리에 영향을 주는 픽셀 조명(될 수 있으면 방향 조명)을 하나만 있게끔 하세요.

- 필요하지 않다면 동적 조명을 사용하지 말고 대신 라이트맵을 사용하세요.

- 가능하다면 압축된 텍스처 형식을 사용하세요. 사용할 수 없다면 32bit보다 16bit를 주로 사용해보세요.

- 필요하지 않다면 안개를 사용하지 마세요.

차폐 배제(Occlusion Culling)의 이점을 알고 차폐가 많은 복잡한(물체가 많은) 정적 장면의 경우 보이는 지오메트리와 draw-calls 양을 낮추기 위해 차폐 배제를 사용하세요. 차폐 배제로 인한 이점에 맞춰 레벨을 제작하세요. (하지만 난 베이직이지.)

“가짜” 원거리 지오메트리를 표현하기 위해 스카이박스를 사용하세요.

- 여러 텍스처를 섞기 위해 다중 패스 방식 대신 픽셀 셰이더나 텍스처 합성기를 사용하세요.

- 직접 셰이더를 작성하고 있다면 가능한 항상 가장 정밀도가 낮은 부동 소수점 형식을 사용하세요.

fixed / lowp : 색상, 조명 정보와 법선용.

half / mediump : 텍스처 UV 좌표용.

float / highp : 픽셀 셰이더에서는 피할 것. 정점 셰이더에서 위치 계산용으로 사용하는 것이 좋습니다.

- 픽셀 셰이더에서 powsincos 등등과 같은 복잡한 수학 연산 사용을 최소화하세요.

- 프래그먼트(화면 픽셀)당 텍스처를 적게 사용하세요.



출처 : http://fetchinist.com/blogs/?p=712

반응형
Posted by blueasa
, |
유니티 관련 3DS Max 에서 작업시 유의사항


- 이곳에서는 3DS Max 에서 유니티 관련 작업을 할 때 유의사항들을 하나하나 정리해 보려 합니다.

익스포트(Export)모델링 데이타는 가급적 FBX 포멧을 사용하자.
: 유니티에서 3DSMAX 와 MAYA 포맷을 지원하지만 내부적으로는 표준 그래픽 교환 포멧인 FBX 로 변환해 관리한다. 가급적 FBX Exporter 툴을 사용해 FBX를 만든 후 유니티로 가져오는 것을 권장한다.

최신의 FBX 익스포터를 사용하자.
: 과거 버전에서 만든 파일을 임포트할 경우 결과가 달라질 수 있으므로 가능한 한 가장 최신의 FBX 익스포터를 사용한다.

FBX를 내보내기 전에 Resource Collector 를 사용해 텍스처를 Asset 폴더로 복사할 수 있다.


3차원 좌표계유니티는 기본적으로 Y축이 위를 향하는 왼손 좌표계를 사용한다.
: FBX 익스포터 옵션에서 Y UP 으로 설정되어 있는지 확인하도록 하자.


스케일(Scale)유니티에서 1의 단위는 1미터를 의미한다.
: Scale Factor 를 통해 모델링을 불러올 때 스케일을 조정할 수 있지만, 가급적 모델링 작업 때 이 단위를 감안하자.


노멀(Normal) 구성대부분의 유니티 셰이더는 기본적으로 뒷면은 그리지 않도록 설정되어 있다.
: 일반적으로 그래픽 소프트웨어는 양면을 다 그리는 반면 유니티 셰이더는 그렇지 않다. 이 때문에 면의 노멀 방향이 잘못되어 있을 경우 그래픽 소프트웨어에서 잘 보이는 물체가 유니티에서는 잘 안 보일 때가 있다.


텍스처(Texture)유니티에서는 이미지가 RGBA 압축된 DXT 이미지인 .dds 형식으로 변환하여 사용된다.
: 유니티에서는 이미지를 .dds 형식으로 변화하여 사용됨으로, tif, psd 같은 대용량 파일도 마음대로 사용해도 된다.

2의 제곱수 사이즈의 텍스처를 사용하자
: 2의 제곱수 이미지를 사용하면 밉매핑(mip-mapping) 이미지가 사용될 때, 아티팩팅(artifacting) 이라는 깜빡임 현상으로 인한 부작용이 거의 없어진다. 또한 컴퓨터 내부적으로 메모리가 2의 제곱수 블록 형태로 사용됨으로 메모리 최적화와 효율성에서 이득이 있다. 가능하다면 이미지는 항상 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 등의 크기로 만들어야 한다.


재질(Material)재질(Material)이름과 텍스처 파일명과 같게 하자
: Unity3D 툴 재질에 텍스처가 자동으로 들어가게 하려면 이름이 같아야 한다.

유니티는 임포트 시점에 객체에 대해 기본 디퓨즈 텍스처만을 생성한다.
: 범프(bump)나 반짝임, 높이, 기타 특수 맵은 직접 추가해야 한다.


메시(Mesh)맥스 객체는 모서리 문제를 막기 위해 에디터블 폴리 대신 에디터블 메시로 병합해야 한다.
: FBX는 회전 모서리를 지원하지 않으므로 내보내는 과정에서 모델이 변경될 수 있다.


애니메이션(Animation)복잡한 애니메이션 계층구조는 유니티에 임포트할 때까지 정사영 방향으로 유지한다.
: 유니티는 비정사영 회전 매트릭스를 지원하지 않는다.

유니티는 현재 모프 타깃 같은 정점 애니메이션을 지원하지 않는다.
: 정점 단위로 객체에 영향을 주는 애니메이션은 항상 뼈대를 사용해 처리해야 한다.

각 비헤이비어(behaviour)나 타임 세그먼트의 시작 및 끝에 있는 변형과 객체에 대해 모두 키를 지정한다.

비헤이비어의 타임 세그먼트는 여러 객체가 같은 이름의 타임 세그먼트나 클립을 사용하지 않는 한 겹치지 않게 한다.


출처 : http://www.devbb.net/viewtopic.php?f=37&t=1120

반응형
Posted by blueasa
, |
유니티의 그림자 기능은 설정 메뉴가 너무 단순해서 별로 할 게 없어 보입니다.
(렌더러에서 체크박스만 체크하고, 퀄리티에서 옵션 조정하는 것이 전부입니다. )
유니티 그림자 시스템의 특징은 투명한 물체에서는 그림자가 동작하지 않으며, 물체의 메시정보에 의해 그림자가 자동으로 만들어지며, 이를 고칠 수 있는 메뉴구성은 존재하지 않습니다.

하지만 유니티 그래픽 팀에서는 셰이더를 사용하여 직접 내가 그림자 모양을 변경할 수 있는 인터페이스를 만들어 두었는데, 이를 소개해드립니다.
우선 셰이더를 제작하고, Pass 구문에 ShadowCaster 라이트 모드를 사용하는 셰이더를 만들면 이 구문에서 물체가 그림자를 생성할 때 이를 가로채 여러분들이 원하는 모양으로 그림자 형태를 변경하는 것이 가능합니다. 

아래 그림 중 왼쪽은 위의 기능을 적용한 예이며, 오른쪽은 일반적인 그림자 생성 결과입니다.






이를 위한 셰이더 코드는 다음과 같습니다. 
붉은 색으로 표시한 Pass의 Tag 구문의 라이트모드 설정을 잘 활용 하시면 여러 표현이 가능하다~ 는 것을 보여드리기 위해 예제는 최대한 심플하게 만들어봤습니다.  (TRANSFER_SHADOW_CASTER 와 같은 매크로들은 UnityCG.cginc에 다 정의되어 있습니다. )

Pass
{
    Name "ShadowCaster"
    Tags { "LightMode" = "ShadowCaster" }
    CGPROGRAM
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"
        
        sampler2D _MainTex;
        fixed _Cutoff;

        struct v2f { 
            V2F_SHADOW_CASTER; 
            float2 uv : TEXCOORD1;
        }
        
        v2f vert(appdata_full v)
        {
            v2f o;
            o.pos = mul( UNITY_MATRIX_MVP, v.vertex ); 
            o.uv = v.texcoord;
            TRANSFER_SHADOW_CASTER(o)
            return o;
        }
        
        float4 frag(v2f IN) : COLOR
        {
            fixed4 c = tex2D( _MainTex, IN.uv );
            clip( c.a - _Cutoff );
            SHADOW_CASTER_FRAGMENT(IN)
        }
    ENDCG
 

프로젝트 파일은 아래에서 다운로드 가능합니다.


참고로 특정 영역이 뚫려있는 그림자의 경우 Transparent/Cutout 계열을 사용하면 자동으로 알파를 제외하고 그림자를 생성해줍니다. 



반응형

'Unity3D > Shadow' 카테고리의 다른 글

Projector Multiply Offset  (0) 2014.04.03
유니티 3D에서 그림자 설정  (0) 2014.03.29
실시간 그림자  (0) 2014.03.07
Posted by blueasa
, |

링크 : http://micropilot.tistory.com/2316

반응형

'Unity3D > Shadow' 카테고리의 다른 글

Projector Multiply Offset  (0) 2014.04.03
셰도우캐스터(ShadowCaster)를 활용한 그림자 생성 변경  (0) 2014.03.29
실시간 그림자  (0) 2014.03.07
Posted by blueasa
, |

unity3D용으로 만들어진 암복호화 알고리즘이다.
(출처: 까먹음... T_T)



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
using UnityEngine;
using System.Collections;
using System.Security.Cryptography;
using System.Text;
using System.IO;
using System;
 
//중략 Key는 32바이트 "12345678901234567890123456789012"
 
 
     public static string Encrypt(string toEncrypt, string key)
    {
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
        byte[] toEncryptArray = UTF8Encoding.UTF8.GetBytes(toEncrypt);
        RijndaelManaged rDel = new RijndaelManaged();
        rDel.Key = keyArray;
        rDel.Mode = CipherMode.ECB;
        rDel.Padding = PaddingMode.PKCS7;
        ICryptoTransform cTransform = rDel.CreateEncryptor();
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
        return Convert.ToBase64String(resultArray, 0, resultArray.Length);
    }
    public static string Decrypt(string toDecrypt, string key)
    {
        byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
        byte[] toEncryptArray = Convert.FromBase64String(toDecrypt);
        RijndaelManaged rDel = new RijndaelManaged();
        rDel.Key = keyArray;
        rDel.Mode = CipherMode.ECB;
        rDel.Padding = PaddingMode.PKCS7;
        ICryptoTransform cTransform = rDel.CreateDecryptor();
        byte[] resultArray = cTransform.TransformFinalBlock(toEncryptArray, 0, toEncryptArray.Length);
        return UTF8Encoding.UTF8.GetString(resultArray);
    }



* 서버에서도 같이 설정해두면 따로 싱크걱정 사라짐 =)


출처 : http://www.wolfpack.pe.kr/828?category=5

반응형
Posted by blueasa
, |


링크 : http://progagmer.blog.me/199532845

반응형
Posted by blueasa
, |

Unity Singleton

Unity3D/Script / 2014. 3. 24. 18:36
using UnityEngine;

public abstract class MonoSingleton<T> : MonoBehaviour where T : MonoSingleton<T>
{
    protected static bool m_bDontDestroyOnLoad = true;
    
    private static bool m_bApplicationQuit = false;
    private static object InstanceLocker = new object();

    private static T m_Instance = null;
    public static T Instance
    {
        get
        {
            if (true == m_bApplicationQuit)
                return null;

            lock (InstanceLocker)
            {
                // Instance requiered for the first time, we look for it
                if (null == m_Instance)
                {
                    T instance = GameObject.FindObjectOfType(typeof(T)) as T;

                    // Object not found, we create a temporary one
                    if (instance == null)
                    {
                        instance = new GameObject(typeof(T).ToString()).AddComponent<T>();

                        // Problem during the creation, this should not happen
                        if (instance == null)
                        {
                            Debug.LogError("Problem during the creation of " + typeof(T).ToString());
                        }
                    }

                    if (instance != null)
                    {
                        Initialize(instance);
                    }
                }

                return m_Instance;
            }
        }
    }

    private static void Initialize(T instance)
    {
        if (m_Instance == null)
        {
            var startTime = System.DateTime.Now;
            m_Instance = instance;

            // 씬 전환 시, 삭제시킬 싱글톤은 부모 객체에 안붙이도록..
            // 싱글톤 시작 시, m_bDontDestroyOnLoad 셋팅 필요.
            if (true == m_bDontDestroyOnLoad)
            {
                GameObject goRoot = GameObject.Find("Singletons") as GameObject;
                if (null == goRoot)
                {
                    goRoot = new GameObject("Singletons");
                    // DontDestroyOnLoad() 등록은 하위 상속받는 쪽에서 하도록 하는 게 나을까?
                    DontDestroyOnLoad(goRoot);
                }
                m_Instance.transform.parent = goRoot.transform;
            }

            m_Instance.OnInitialize();
            var period = System.DateTime.Now - startTime;
            if (period.TotalSeconds > 1.0f)
            {
                var name = m_Instance.ToString();
                Debug.LogWarning("Profile Warnning. Singletion {" + name + "} too long init time : " 
                                 + period.TotalSeconds.ToString("F") + "Seconds");
            }
        }
        else if (m_Instance != instance)
        {
            DestroyImmediate(instance.gameObject);
        }
    }

    private static void Destroyed(T instance)
    {
        if (m_Instance == instance)
        {
            m_Instance.OnFinalize();
            m_Instance = null;
        }
    }

    public void CreateSingleton() { }
    // [Warning] GameObject에 Component로 미리 등록된 상태에서는 OnInitialize() 호출 안됨.
    public virtual void OnInitialize() { }
    // [Warning] GameObject에 Component로 미리 등록된 상태에서는 OnFinalize() 호출 안됨.
    public virtual void OnFinalize() { }
    protected virtual void CheckDontDestroyOnLoad() { }

    private void Awake()
    {
        Initialize(this as T);
    }

    void OnDestroy()
    {
        Destroyed(this as T);
    }

    private void OnApplicationQuit()
    {
        m_bApplicationQuit = true;
        Destroyed(this as T);
    }
}


반응형
Posted by blueasa
, |

유니티에서 SQLiteKit 에셋을 사용하기 위해 Excel -> db 파일로 변환 할 때 나오는 syntax error의 의미가 모호해서 정리겸 남겨놓는다.


1) 칼럼 값이 비어있을 때 나는 에러.(꼭 칸을 채워야 함)




2) SQLiteKit을 쓸 때, 테이블에서 쓸 수 없는 문자가 몇 있는 것 같다.

    더 있을 지는 모르지만 내가 테스트 해본 것 까지만 정리..


2-1) 테이블값에서 '-', '(', ')', ' '(빈칸) 은 사용 못함.


2-2) 테이블값에서 첫글자가 숫자로 시작할 수 없음.('_'는 허용됨.)

      'a1_1' 등으로 영어 뒤 숫자는 사용가능.





반응형
Posted by blueasa
, |

VS2013을 깔았는데 Unity3D의 External Tools에 리스트가 뜨지 않길래 찾아보니 수동 등록 방법이 있다.


How to use Visual Studio 2013

  1. In Unity Editor go to Edit->Preferences->External Tools and In External Script Editor choose Browse from the drop down box.
  2. Browse to and select C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE\devenv.exe.
  3. The External Script Editor should automatically show your selected editor as Visual Studio 2013.
  4. That’s it! It should just work from that point on.

Visual Studio fails to load for me!

Some people may have trouble loading VS2013 even after applying the correct settings above. The solution, for the time being, is to run Visual Studio 2013 beforehand and then the Unity Editor will successfully load its own project instance.

It works now but its not quite right

The above method isn't perfect and that is because Unity3D just doesn't properly generate the correct project files. If you don't like the limitations of the above method and you're able to afford it the best option right now is still buy the UnityVS plugin for Unity3D.



출처 : http://stackoverflow.com/questions/19889848/working-with-unity3d-and-visual-studio-2013

반응형
Posted by blueasa
, |
// 해당 폴더가 있는지 체크하기 위해..
Object oTargetFolder = AssetDatabase.LoadAssetAtPath("Assets/Resources", typeof(Object));

if(null == oTargetFolder)
{
    // 못찾으면 폴더 없다고 보고 폴더 생성.
    AssetDatabase.CreateFolder("Assets", "Resources");

    // 한 번 더 찾기 시도..
    Object oTargetFolder2 = AssetDatabase.LoadAssetAtPath("Assets/Resources", typeof(Object));

    if(null != oTargetFolder2)
    {
        // 있으면 셀렉트 되도록 대입..
        Selection.activeObject = oTargetFolder2;
    }
}
else
{
    // 있으면 셀렉트 되도록 대입..
    Selection.activeObject = oTargetFolder;
}


우선 위와같은 방법으로 했는데.. 더 좋은 방법이 있는지는 모르겠다..

폴더도 오브젝트일까? 라는 생각으로 해봤는데 오브젝트인가보다..잘되네..@ㅅ@;;

반응형
Posted by blueasa
, |