TA/Unity2013. 9. 9. 17:46

출처 : http://egohim.blog.me/70170987774

 

 

 

참고 : Practical Guide to Optimization for Mobiles - Future & High End Devices

참고 : Practical Guide to Optimization for Mobiles - Graphics Methods

참고 : Practical Guide to Optimization for Mobiles - Scripting and Gameplay Methods

참고 : Practical Guide to Optimization for Mobiles - Rendering Optimizations

참고 : Practical Guide to Optimization for Mobiles - Optimizing Scripts

 

// Practical Guide to Optimization for Mobiles 

참고 : http://docs.unity3d.com/Documentation/Manual/iphone-PracticalScriptingOptimizations.html

1.Class vs Struct

Classes are objects and behave as references. If Foo is a class and

 Foo foo = new Foo();

 MyFunction(foo); 

then MyFunction will receive a reference to the original Foo object 

that was allocated on the heap. 

Any changes to foo inside MyFunction will be visible anywhere foo is referenced.

-C#에서 클래스는 함수 인자로 넘길 대 레퍼런스화 되서 작동 한다만약 Foo클래스가 Foo foo = new Foo();로 선언되었다면

  MyFunction(foo);에서 MyFunction은 힙 메모리 영역에 선언된 Foo 오브젝트의 레퍼런스로 받게 된다.

  만약 foo MyFunction안에서 어떤 변화가 있다면 foo의 참조를 받는 그 어디에서라도 그것이 적용되게 된다.

 

If Foo is a struct and

 Foo foo = new Foo();

 MyFunction(foo); 

then MyFunction will receive a copy of foo. 

foo is never allocated on the heap and never garbage collected. 

If MyFunction modifies it's copy of foo, the other foo is unaffected.

-만약 Foo가 구조체(Struct)로 선언되어있다면 Foo foo = new Foo(); MyFunction(foo);로 선언된 MyFunction(foo); 에서

  MyFunction함수는 foo가 복사 되어 받게 된다.

  foo는 절대 힙메모리 영역에 할당되지 않으며또한 절대 가비지 콜렉트되지 않는다.

  만약 MyFunction에서 foo가 넘어가면 foo가 복사되기 때문에 함수내에서 변경해도 다른 참조된 foo에 영향을 주지 않고,

  스코프를 벗어나면 자동 소멸 된다.

 

 

// Understanding Automatic Memory Management

참고 : http://docs.unity3d.com/Documentation/Manual/UnderstandingAutomaticMemoryManagement.html

 

2. String 배열의 메모리 단편화 문제 

function ConcatExample(intArray: int[]) {

 var line = intArray[0].ToString();

 for (i = 1; i < intArray.Length; i++) {

  line += ", " + intArray[i].ToString();

 }

 return line;

}

 

-> String Builder 사용을 추천.

StringBuilder sb = new StringBuilder();

ShowSBInfo(sb);

sb.Append("This is a sentence.");

ShowSBInfo(sb);

for (int ctr = 0; ctr <= 10; ctr++) {

 sb.Append("This is an additional sentence.");

 ShowSBInfo(sb);

 

3. 가변 시에만 메모리 할당 처리

 var scoreBoard: GUIText;

 var score: int;

 

 function Update() {

  var scoreText: String = "Score: " + score.ToString();

  scoreBoard.text = scoreText;

 }

...will allocate new strings each time Update is called and generate a constant trickle of new garbage. Most of that can

be saved by updating the text only when the score changes:-
매 업데이트 할때 마다 새로운 String 생성으로 가비지가 생성되는 비효율적인 문제로 텍스트를 가변 상황에만 String할당.

 var scoreBoard: GUIText;

 var scoreText: String;

 var score: int;

 var oldScore: int;

 

 function Update() {

  if (score != oldScore) {

   scoreText = "Score: " + score.ToString();

   scoreBoard.text = scoreText;

   oldScore = score;

  }

 }

 

 

4. 배열 생성 반환 함수의 잠재적인 문제
potential problem occurs when a function returns an array value:-

 function RandomList(numElements: int) {

  var result = new float[numElements];

  for (i = 0; i < numElements; i++) {

   result[i] = Random.value;

  }

 

  return result;

 }

This type of function is very elegant and convenient when creating a new array filled with values. However, if it is called repeatedly
then fresh memory will be allocated each time. Since arrays can be very large, the free heap space could get used up rapidly,
resulting in frequent garbage collections. One way to avoid this problem is to make use of the fact that an array is a reference type. An array passed into a function as a parameter can be modified within that function and the results will remain after the function returns. A function like the one above can often be replaced with something like:-

 function RandomList(arrayToFill: float[]) {

  for (i = 0; i < arrayToFill.Length; i++) {

   arrayToFill[i] = Random.value;

  }

 }

This simply replaces the existing contents of the array with new values. Although this requires the initial allocation of the array to be done in the calling code (which looks slightly inelegant), the function will not generate any new garbage when it is called.

4. Garbage Collection 
호출 전략 
4-1. Small heap with fast and frequent garbage collection (빠르고 적은 힙 그리고 빈번한 가비지 콜렉션 방식)
This strategy is often best for games that have long periods of gameplay where a smooth framerate is the main concern. A game like this will typically allocate small blocks frequently but these blocks will be in use only briefly. The typical heap size when using this strategy on iOS is about 200KB and garbage collection will take about 5ms on an iPhone 3G. If the heap increases to 1MB, 

the collection will take about 7ms. It can therefore be advantageous sometimes to request a garbage collection at a regular frame interval. This will generally make collections happen more often than strictly necessary but they will be processed quickly and with minimal effect on gameplay:-
- iOS iPhone 3G 
에서 200KB garbage collection하는 데 5ms 가 걸리고,
                                 1MB
   garbage collection하는데 7ms 가 걸린다. - 

 if (Time.frameCount % 30 == 0)

 {

    System.GC.Collect();

 }

 

However, you should use this technique with caution and check the profiler statistics to make sure that it is really reducing collection time for your game.
그러나 위 방식을 체택 할 경우 프로파일러 통계로 명확하게 체크 할 것을 요한다.

4-1. Large heap with slow but infrequent garbage collection (큰 힙과 느리지만빈번하지 않은 가비지 콜렉션 방식)

This strategy works best for games where allocations (and therefore collections) are relatively infrequent and can be handled during pauses in gameplay. It is useful for the heap to be as large as possible without being so large as to get your app killed by the OS due to low system memory. However, the Mono runtime avoids expanding the heap automatically if at all possible. You can expand the heap manually by preallocating some placeholder space during startup (ie, you instantiate a "useless" object that is allocated purely for its effect on the memory manager):-
-
최고의 게임에서 빈번하지 않게 가비지 콜렉트를 호출하는 전략은 게임 플레이가 멈춘 동안에 다루는 것이다. ... 

 function Start() {

  var tmp = new System.Object[1024];

 

  // make allocations in smaller blocks to avoid them to be treated in a special way, which is designed for large blocks

         for (var i : int = 0; i < 1024; i++)

   tmp[i] = new byte[1024];

 

  // release reference

         tmp = null;

 }

 

A sufficiently large heap should not get completely filled up between those pauses in gameplay that would accommodate a collection. When such a pause occurs, you can request a collection explicitly:-
System.GC.Collect();
Again, you should take care when using this strategy and pay attention to the profiler statistics rather than just assuming it is having the desired effect.

// Practical Guide to Optimization for Mobiles - Optimizing Scripts
http://docs.unity3d.com/Documentation/Manual/iphone-PracticalScriptingOptimizations.html#Object%20Pooling
 

// Optimization for Mobiles - Scripting and Gameplay Methods

http://docs.unity3d.com/Documentation/Manual/iphone-OptimizedScriptingMethods.html

 

 

// 마소 C# 메모리 최적화 글 -good

http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=40743

 

// 마소 유니티 메모리 최적화 글

http://www.imaso.co.kr/?doc=bbs/gnuboard.php&bo_table=article&wr_id=41284

 

이하 인용....

유니티 스크립트 중에 최적화란 관점에서는 중요한 두 가지 함수가 존재한다명시적으로 GC를 호출하는 System.gc.collect와 

현재 사용하지 않는 리소스를 해제하는 Resources.Unload UnusedAssets란 함수다보통 scene이 바뀌거나 메모리를 

한번 비우고 가고 싶을 때 호출하게 되는데 두 함수만 열심히 호출한다고 해서 모든 문제가 해결되는 것은 아니다

 

...

개발하던 게임에서는 GUI를 위한 여러 텍스처들이 사용되고 있었는데 몇 개의 텍스처가 NPOT(non power of two)로 제작돼 있었다

OpenGL ES2를 지원하는 최근의 디바이스들은 NPOT 텍스처를 제한적으로 지원하고 있으나 유니티는 호환성을 위해 

NPOT 텍스처의 경우 내부적으로 별도의 처리를 하는 것으로 보인다

프로파일링 결과 POT 대비 2배의 메모리를 사용하는 것으로 생각되는데비디오 메모리를 많이 사용하는 게임에서는 특히 

유념해야 할 부분이다.

 

Posted by 프리랜서 디자이너
TA/Unity2013. 9. 9. 17:36

그래픽 성능 최적화

Desktop

게임이 끊김 없이 부드럽게 동작하는 것은 게임의 성공 여부에 매우 중요 합니다. 유니티가 이를 위해 존재합니다. 저희들은 다양한 하드웨어에 유니티 iOS가 빨리 동작하도록 많은 시간과 노력을 기울였습니다. 아래에는 게임의 스피드를 최대화 하기 위한 몇몇 간단 한 안내서를 소개합니다.

줄여서 얘기하면 – 통합(combine), 통합, 통합

  • 성능을 신경 쓰신다면, 메쉬들을 통합하세요.
  • 성능을 신경 쓰신다면, 통합된 메쉬들이 같은 재료(material)와 질감을 공유하도록 확인하세요.
  • ProfilerRendering Statistics 창이 유용할 것입니다!

자세히 살펴보면:

현대의 그래픽 카드들은 많은 다각형을 표현해 내는데 익숙하지만, 그래픽 카드에 모든 일괄처리(batch)들은 많은 과부하를 야기 합니다. 만약, 100개의 삼각형 오브젝트가 있는 것은 1500개의 삼각형을 표현해 내는 것만큼 많은 성능 소모가 일어 납니다. 최적의 표현 성능을 내는 이상적인 장소는 메쉬당 1500-4000개의 삼각형입니다.

Mesh Renderer가 부탁된 오브젝트들을 표현하는 것은 성능의 일정한 대가를 치러야 합니다. 보기 절두체(view frustum)내에서 그 대가를 치릅니다. 장면(scene)내에서 빈 GameObjects들을 많이 가지고 있는 것은 표현 비용이 없습니다.

  • 표현 성능을 향상 시키는 가장 좋은 방법은 오브젝트들을 결합해서 각 메쉬가 1500개 또는 더 이상의 오브젝트를 가지고, 전체 메쉬를 위해 하나의 Material를 사용하는 것입니다.

재료를 공유하지 않는 두개의 오브젝트들을 결합하는 것은 성능의 부하를 주지 않는다는 것을 이해해야 합니다. 효율적으로 결합하려면, 메쉬가 통합 후에 하나의 재료를 쓴다는 것을 확인하시기 바랍니다.

오브젝트들을 결합 할 때 한가지는 알아야 합니다. 장면에 많은 조그마한 빛들을 사용하면, 근접한 오브젝트들을 결합 하는 것이 더 합리적입니다.

많은 재료를 가지는 메쉬를 표현하는 비용은, 각 재료로 다수의 렌더러(renderer)를 가지는 것과 같은 비용 입니다. 다수의 재료들을 가지는 가장 보편화된 이유는 두 개의 메쉬들은 같은 질감들을 공유하지 않습니다. 표현 성능을 최적화 시키려면, 통합하는 오브젝트들이 같은 질감을 공유하도록 하셔야 합니다.

  • 유니티는 많은 다각형을 밀어 표현 하는것에 강점이 있다. 유니티는 모든 기하를 그래픽 카드로 업로드 하는데, 이는 좋은 캐쉬(cache) 효율과 최적화된 데이터 배열을 위해서이다.
  • 단지 그래픽 카드는 많은 수의 일괄처리를 다룰 필요가 없음을 확인해야 한다.
  • 전면 렌더링 통로 Forward rendering path를 사용하면, 오브젝트에 영향을 주는 Pixel Lights의 개수는 성능에 많은 영향을 준다.

전면 렌더링 통로에서의 픽셀 불빛들

주의: 이는 오직 전면 렌더링 통로 Forward rendering path 에서만 적용이 됩니다.

픽셀 불빛을 사용하면, 각각의 GameObject는 오브젝트에 영향을 주는 픽셀 불빛의 갯수 만큼 표현되어야 합니다. 멀리 떨어져 있는 두 오브젝트를 결합하면, 오브젝트의 크기가 증가할 것이고, 이 큰 오브젝트에 영향을 주는 많은 물빛들을 가지게 될 것입니다. 오브젝트들이 분리되어있으면, 멀리 떨어진 메쉬의 부분에 빛들이 적용될 필요는 없습니다.이는 통합된 메쉬를 표현하는데 통합되지 않는 메쉬(따라서 아무것도 저장하지 않는) 의 개수 만큼 표현하는 결과가 생깁니다. 이런 이유로, 멀리 떨어진 GameObjects들을 각각의 메쉬들로 보존해야 합니다.

메쉬를 표현할때, 유니티는 메쉬 주위의 모든 불빛을 찾습니다. 그리고, 어떤 빛들이 메쉬에 가장 영향을 미치는지 알아냅니다. QualitySettings은 얼마나 많은 빛이 픽셀 빛과 정점 (vertex) 빛으로 도래되는지를 변경할 때 사용합니다.

모든 빛들은 메쉬로부터 얼마나 떨어지고, 얼마나 강도가 있는지에 기반하여 중요성을 계산합니다.

어떤 빛들은 다른 빛들보다 게임의 맥락에서 더 중요합니다. 이러한 이유로, 모든 빛은 Render Mode 설정을 가집니다. 이 설정은 ImportantNot Important로 나눠집니다.

헤드 라이트를 가진 게이머의 차가 밤에 운전하는 것을 상상해 보십시오. 헤드 라이트들은 게임에서 가장 중요한 불빛들입니다. 이러한 이유로, 헤드라이트의 렌더 상태는 Important로 설정되어야 합니다.

별로 중요하지 않는 불빛을 가지고, 픽셀 빛으로부터 시각적으로 얻는 것이 없다면 렌더 상태는 Not Important로 설정합니다. 이런 방식으로 렌더링 성능이나 시각적 성능을 낭비하지 않습니다.

레이어당 누락 거리

그리기 호출의 개수를 줄이기 위해 작은 오브젝트들을 누락시키고 싶을 때가 있습니다. 예를 들어, 조그만 바위나 잔재는 커다란 빌딩보다 작은 거리에서는 보이지 않습니다. 이를 위해서는, 작은 오브젝트들을 분리된 레이어에 놓고, 레이어당 누락거리를 Camera.layerCullDistances 스크립트 함수를 사용하여 설정하십시오.

그림자들

데스크톱 플랫폼에서 배치한다면, 그림자들에 신경을 써야 합니다. 그림자들은 일반적으로 (성능상의)비용이 많이 듭니다. 그림자들이 정확하게 사용되지 않으면 게임의 성능에 많은 부하를 줍니다. 그림자들에 대한 더 많은 정보는 Shadows page를 읽으시길 바랍니다.

주의: 그림자들은 현재 iOS 나 Android 디바이스들에는 지원되지 않습니다.

더 살펴보기

iOS

iOS를 위해서 컨텐트의 최적화를 원한다면 learn more about iOS hardware devices 페이지를 참조 하십시오.

알파 테스팅

데스크톱과는 반대로, 알파테스팅 (또는 픽셀 쉐이더에서 discard$ / clip$$ 연산)은 iOS에서 성능상 비용이 많이 듭니다. 알파 테스트 쉐이더를 알파 블렌드로 교체를 원하시면, 그렇게 하십시오. 알파 테스트가 정말 필요하시면, 보이는 알파 테스트 픽셀 지역을 최소로 유지 시키십시오.

정점 성능

일반적으로 iPhone 3GS 나 새로운 디바이스들을 타겟으로 할때, 프레임당 40K나 더 적은 정점을 목표로 합니다. MBX GPU가 장착된iPhone, iPhone 3G, 1세대 2세대 iPod Touch 경우 프레임당 10K나 더 적은 정점을 목표로 합니다.

라이팅 성능

픽셀당 동적 라이팅(lighting)은 모든 영향 받는 픽셀에 중요한 비용이 추가 되고, 다중 패스들에 렌더링 오브젝트들을 이끌 수 있습니다. 하나의 오브젝트에 영향을 주는 하나의 Pixel Light보다 픽셀 라이트를 더 가지는 것을 피하시고, 방향성 빛을 선호하시길 바랍니다. Pixel LightRender Mode 설정이 Important로 설정되어 있음을 명심하시기 바랍니다.

정점당 동적 라이팅은 정점 변환에 많은 비용이 더 추가 됩니다. 하나의 오브젝트에 영향을 줄때는 다중 불빛을 피하시기 바랍니다. 정적 오브젝트들을 위해서는 베이크 라이팅 (bake lighting)을 사용하십시오.

모델 기하 최적화

모델 기하를 최적화 할 때, 두 가지 기초 룰이 있습니다:

  • 필요하지 않다면, 더 많은 추가 면을 사용하지 마세요.
  • UV매핑솔기(seam)의 수를 유지하고, 하드 모서리(hard edge)를 가능한 적게 하십시오.

그래픽 하드웨어가 프로세싱하는 실질적인 정점의 개수는 3D 어플리케이션에 표시되는 것과는 같지 않습니다. 모델링 어플리케이션들은 모델을 이루는 포인트들, 즉 기하 정점 카운트를 표시합니다.

그래픽 카드들은, 몇몇 정점들은 구분 되어야 합니다. 정점이 다중의 법선(normal)들 (하드 모서리 위에서) 을 가지거나, 다중의 UV 좌표를 가지거나, 다중의 꼭지점 색상을 가지면, 이는 분리되어야 합니다. Unity에서 보는 정점의 숫자는 3D 어플리케이션에서 진열 되는 것과 항상 다릅니다.

질감 압축

iOS 의 네이티브 PVRT compression formats 압축 포맷을 사용하십시오. 질감의 사이즈를 감소시킬 뿐만 아니라(더 빠른 불러오기 시간과 더 작은 메모리 사용), 렌더링의 성능을 증가 시킵니다. 압축된 질감은32bit RGBA에 비교해서 메모리 대역폭의 아주 일부분만 필요합니다. 성능 비교를 위해서는 iOS Hardware Guide를 참조하십시오.

몇몇 이미지는 PVRT 압축 질감의 알파 채널에서 시각적 조형물로 되기 싶습니다. 그런 경우 이미지 소프트웨어에 PVRT 압축 변수들의 직접적인 변경을 원할 수 있습니다. PVRT 포맷을 만든 Imagination Tech의 PVRTexTool을 사용하여 PVR export plugin을 설치해서 직접적인 변경이 가능합니다. ..pvr 확장을 가진 압축 이미지는 유니티 에디터에 가져오기 될 것이며, 수동으로 설정된 압축 변수들은 보존 될 것입니다.

PVRT 압축 포맷이 충분한 시각적 질을 전달하지 않는다면, UI 질감과 같은 추가의 이미지 작업이 필요합니다. 이 경우 32bit RGBA 질감대신 16bit 질감의 사용을 고려해야 합니다. 최소한, 메모리 대역폭이 반으로 줄 것입니다.

성능 좋은 쉐이더를 작성하기 위한 팁들

iPhone3GS 이후로 GPU들은 픽셀과 정점 쉐이더(shader)들을 충분히 지원하지만, 복잡한 픽셀당 기능을 가진 데스코톱 쉐이더의 성능과 초당 30프레임들을 동작하는 iOS디바이스의 성능을 추월하는 기대는 하면 안됩니다. 대부분 쉐이더 들은 편리하게 최적화 되어있고, 연산과 질감은 좋은 프레임 비율을 달성하기 위해서는 최소화 하여야 합니다.

복잡한 수식 연산들

수식 연산들(pow,, exp, log, cos, sin, tan)은 GPU에 많은 부하를 줍니다. 최고의 방법은 부분당(per fragment) 하나의 연산 이상을 가지지 않는 것입니다. 때로는 질감 찾기(lookup)가 더 좋은 대안입니다.

자신만의 규격화된 normalize, dot, inversesqrt 사용을 회피하십시오. 항상 내장되어있는 연산들을 사용하십시오. 이것이 더 좋은 코드를 생성할 것입니다.

Disscard 연산은 부분들(fragments)을 느리게 만들것입니다.

부동소수 연산들

사용자 쉐이더들을 작성할 때 부동 소수 변수들의 소수점 자리를 명시하십시오. 좋은 성능을 위해서는 작은 포맷이 더 중요하다는 것은 매우 중요합니다.

쉐이더가 GLSL ES로 쓰여지면, 소수점 자리는 다음과 같습니다:

  • highp - full 32 비트의 부동소수 포맷입니다. 정점변환에 적합하지만 가장 느립니다
  • mediump - 16비트의 부동소수 포맷입니다. 질감 UV 좌표에 적합합니다. 대략 highp보다 x2 빠릅니다.
  • lowp - 비트의 부동소수 포맷입니다. 색상과 빛 연산, 그리고 고성능 연산에 적합합니다. highp보다는 __x4 배 정도 빠릅니다.

쉐이더가 GG또는 표면 쉐이더로 쓰여지면, 소수점은 다음과 같습니다:

  • float - - GLSL ES 에서 highp 와 유사, 가장 느림
  • half - GLSL ES 에서 mediump와 유사, float보다 _x2__ 빠름
  • fixed - GLSL ES 에서 lowp와 유사, float보다 4x4 빠름

일반적인 쉐이더 성능을 알아보시려면 Shader Performance page 페이지를 참조하세요.

하드웨어 문서

Apple hardware 문서를 공부하고 쉐이더를 작성best practices for writing shaders하는데 시간을 가지시길 바랍니다. 부동 소수점의 힌트를 더 공격적으로 사용하길 권유합니다.

Lightmaps으로의 Bake Lighting

정적 라이팅의 장면을 Unity내의 내장된 Lightmapper를 사용해서 베이크(bake)하십시오. lightmapped 환경을 생성하는 과정은 Unity에서 장면에 빛을 배치하는 것보다 더 시간이 걸립니다. ¬¬그러나:

  • 더 많이 빠릅니다 (2-3 배, 2 픽셀 라이트)
  • 더 좋게 보입니다. 왜냐하면, 전체적 조명을 베이크 할수 있고, lightmapper는 결과들을 부드럽게 할 수 있습니다

재료들 공유

다수의 오브젝트들이 같은 카메라로 표현되면, 유니티 iOS는 더 다양한 내부적 최적화를 할 수 있을 것입니다. 예:

  • 다양한 렌더 상태들을 OpenGL ES로 하는 것을 피함.
  • 정점과 픽셀 프로세싱에 필요한 다양한 종류의 변수들 연산을 피함
  • 그리기(draw)호출들의 감소를 위한 작은 오브젝트들의 일괄처리
  • 그리기 호출을 줄이기 위한 정적 속성을 가능하게 하는 크고 작은 오브젝트들의 일괄 처리

모든 이런 최적화들은 CPU 사이클들을 줄여줄 것입니다. 그러므로, 질감들을 하나의 지도로 합하고 같은 재료(material)을 사용하기 위한 다수의 오브젝트를 만드는 것은 비용을 줄이므로, 권유합니다!

게임을 빠르게 하기 위한 간단한 체크리스트

  • 정점 카운트를 아래로 유지하세요:
    • iPhone 3GS와 더 최신의 디바이스를 타겟으로 할때는 프레임당40K 를 하세요 (SGX GPU를 사용).
    • 더 오래된 디바이스들은 프레임당10K 로 하세요 (MBX GPU를 사용)
  • 내장 쉐이더를 사용한다면, Mobile 카테고리를 살펴보세요. Mobile/VertexLit 는 현재 가장 빠른 쉐이더입니다.
  • 장면당 다른 재료(material)의 개수를 낮게 유지하세요- 가능하면 다른 오브젝트들 사이에서 더 많은 재료를 공유하세요.
  • 내부 최적화를 위해서 움직이지 않는 오브젝트들에게 Static 속성을 설정하세요.
  • 가능한 질감들을 위해서는 PVRTC 포맷을 사용하세요. 아니면, 32bit 대신 16bit 질감을 선택하세요.
  • 통합기(combiners)또는 픽셀 쉐이더를 사용하세요. 이는 다중 패스 접근법 대신에 부분당 몇몇 질감을 혼합하기 위함입니다.
  • 사용자 설정 쉐이더를 작성시에는, 항상 가장 작은 부동 소수점을 사용하세요:
    • fixed / lowp -- 칼라와 라이팅 정보, 법선들을 위해서는 완벽합니다,
    • half / mediump -- 질감 UV 좌표들을 위해서 쓰입니다,
    • float / highp -- 픽셀 쉐이더에서는 피합니다. 정점 쉐이더에서 정점 위치 계산을 위한 사용에 괜찮습니다.
  • 픽셀 쉐이더에서 복잡한 수식 연산(pow, sin, cos 등)을 최소화 합니다.
  • 필요하지 않으면 Pixel Lights는 쓰지 않습니다. – 기하에 영향을 주는 (가능한 방향성의) 하나의 픽셀 라이트를 선택하세요.
  • 필요하지 않으면 동적 라이트를 사용하지 않습니다 – 베이크 라이트를 대신 선택하세요.
  • 부분당 (per fragment) 더 작은 질감을 사용하세요.
  • 알파 테스팅을 피하세요. 알파 블렌딩(alpha-blending)을 대신 사용하세요.
  • 필요하지 않으면 안개를 사용하지 마세요.
  • 폐색 누락(Occlusion culling) 의 장점을 알아보시고, 복잡한 정적 장면에 많은 폐색이 있을 시에는 가시 기하와 그리기 호출의 양을 줄이기 위해서 사용하세요. 폐색 누락으로부터 어떤 이득의 단계를 얻을 것인지 계획하세요.
  • 원거리 기하를 “위장(fake)” 위해서는 스카이박스(skybox)들을 사용하세요.

더 살펴보기

Android

라이팅 성능

픽셀당 동적 라이팅(lighting)은 모든 영향 받는 픽셀에 중요한 비용이 추가 되고, 다중 패스들에 렌더링 오브젝트들을 이끌 수 있습니다. 하나의 오브젝트에 영향을 주는 하나의 픽셀 라이트 보다 Pixel Light를 더 가지는 것을 피하시고, 방향성 빛을 선호하시길 바랍니다. Pixel LightRender Mode 설정이 Important로 설정되어 있음을 명심하시기 바랍니다.

정점당 동적 라이팅은 정점 변환에 많은 비용이 더 추가 됩니다. 하나의 오브젝트에 영향을 줄때는 다중 불빛을 피하시기 바랍니다. 정적 오브젝트들을 위해서는 베이크 라이팅 (bake lighting)을 사용하십시오.

모델 기하 최적화

모델 기하를 최적화 할 때, 두 가지 기초 룰이 있습니다:

  • 필요하지 않다면, 더 많은 추가 면을 사용하지 마세요
  • UV매핑솔기(seam)의 수를 유지하고, 하드 모서리(hard edge)를 가능한 적게 하십시오

그래픽 하드웨어가 프로세싱하는 실질적인 정점의 개수는 3D 어플리케이션에 표시되는 것과는 같지 않습니다. 모델링 어플리케이션들은 모델을 이루는 포인트들, 즉 기하 정점 카운트를 표시합니다.

그래픽 카드들은, 몇몇 정점들은 구분 되어야 합니다. 정점이 다중의 법선(normal)들 (하드 모서리 위에서) 을 가지거나, 다중의 UV 좌표를 가지거나, 다중의 꼭지점 색상을 가지면, 이는 분리되어야 합니다. Unity에서 보는 정점의 숫자는 3D 어플리케이션에서 진열 되는 것과 항상 다릅니다.

질감 압축

모든OpenGL ES 2.0 를 지원하는 안드로이드 디바이스들은 ETC1 compression format을 지원합니다. 그러므로, ETC1을 선호하는 질감 포맷으로 사용하길 권유합니다. 압축된 질감은 질감의 사이즈를 줄이는데 중요할 뿐만 아니라(빠른 불러오기 시간과 더 작은 메모리 사용), 렌더링 성능의 향상도 크게 기여합니다. 압축된 질감은32bit RGBA에 비교해서 메모리 대역폭의 아주 일부분만 필요합니다.

만약Nvidia Tegra 나 Qualcomm Snapdragon과 같은 그래픽 구조를 타겟으로 하면, 그러한 구조에 전속적인 압축 포맷을 사용하는 것도 고려해 볼만 합니다. 안드로이드 마켓은질감 압축 포맷의 지원의 필터링을 허락합니다. DXT compressed textures와 같은 .apk와 같은 배포파일은 지원하지 않는 디바이스에서는 압축이 허용되지 않을 수 있습니다.

Mip Maps 허용

항상 Generate Mip Maps 를 허용하는 것이 좋습니다. 질감 압축이 GPU 렌더링시 질감 데이터의 전송의 한계를 돕듯이, mip mapped 질감은 GPU가 더 작은 삼각형으로 낮은 해상도를 사용하게 하는 것을 가능하게 합니다. 이 규칙의 예외는 texel(texture pixel)이 UI 요소들이나 순수 2D게임에서 렌더된 스크린 픽셀에 1:1 매핑하는 것입니다.

성능 좋은 쉐이더를 작성하기 위한 팁들

모든 안드로이드OpenGL ES 2.0 GPU들은 픽셀과 정점 쉐이더(shader)들을 충분히 지원하지만, 복잡한 픽셀당 기능을 가진 데스코톱 쉐이더의 성능과 초당 30프레임들을 동작하는 안드로이드 디바이스의 성능을 추월하는 기대는 하면 안됩니다. 대부분 쉐이더 들은 편리하게 최적화 되어있고, 연산과 질감은 좋은 프레임 비율을 달성하기 위해서는 최소화 하여야 합니다.

복잡한 수식 연산들

수식 연산들(pow, exp, log, cos, sin, tan)은 GPU에 많은 부하를 줍니다. 최고의 방법은 부분당(per fragment) 하나의 연산 이상을 가지지 않는 것입니다. 때로는 질감 찾기(lookup)가 더 좋은 대안입니다.

자신만의 normalize, dot, inversesqrt 연산들의 사용을 회피하십시오. 항상 내장되어있는 연산들을 사용하십시오. 이것이 더 좋은 코드를 생성할 것입니다.

Discard 연산은 부분들(fragments)을 느리게 만들 것입니다.

부동소수 연산들

사용자 쉐이더들을 작성할 때 부동 소수 변수들의 소수점 자리를 명시하십시오. 좋은 성능을 위해서는 작은 포맷이 더 중요하다는 것은 매우 중요합니다.

쉐이더가 GLSL ES로 쓰여지면, 소수점 자리는 다음과 같습니다:

  • highp - 32비트의 부동소수 포맷입니다. 정점변환에 적합하지만 가장 느립니다
  • mediump - 16비트의 부동소수 포맷입니다. 질감 UV 좌표에 적합합니다. 대략 highp보다 x2 배 빠릅니다
  • lowp - 10비트의 부동소수 포맷입니다. 색상과 빛 연산, 그리고 고성능 연산에 적합합니다. highp보다는 x4 배 정도 빠릅니다

쉐이더가 GG또는 표면 쉐이더로 쓰여지면, 소수점은 다음과 같습니다:

  • float - GLSL ES 에서highp와 유사, 가장 느림
  • half - GLSL ES 에서 mediump와 유사, float보다 x2 빠름
  • fixed - GLSL ES 에서 lowp와 유사, ffloat보다 x4

일반적인 쉐이더 성능을 알아보시려면 Shader Performance page 페이지를 참조하세요. 인용된 성능 그림들은즉 삼성 Nexus S와 같은 기기들에 사용가능한PowerVR 그래픽 환경을 기반으로 합니다. 다른 하드웨어 환경들은 레지스터 정밀(precision)의 감소로부터 덜 혹은 더 수혜를 받을 것입니다.

Lightmaps 으로의 Bake Lighting

정적 라이팅의 장면을 Unity내의 내장된 Lightmapper를 사용해서 베이크(bake)하십시오. lightmapped 환경을 생성하는 과정은 Unity에서 장면에 빛을 배치하는 것보다 더 시간이 걸립니다, 그러나:

  • 더 많이 빠릅니다 (2-3 배, 2 픽셀 라이트)
  • 더 좋게 보입니다. 왜냐하면, 전체적 조명을 베이크 할수 있고, lightmapper는 결과들을 부드럽게 할 수 있습니다

재료들 공유

다수의 오브젝트들이 같은 카메라로 표현되면, 유니티 안드로이드는 더 다양한 내부적 최적화를 할 수 있을 것입니다. 예:

  • 다양한 렌더 상태들을 OpenGL ES로 하는 것을 피함.
  • 정점과 픽셀 프로세싱에 필요한 다양한 종류의 변수들 연산을 피함
  • 그리기(draw)호출들의 감소를 위한 작은 오브젝트들의 일괄처리
  • 그리기 호출을 줄이기 위한 정적 속성을 가능하게 하는 크고 작은 오브젝트들의 일괄 처리

모든 이런 최적화들은 CPU 사이클들을 줄여줄 것입니다. 그러므로, 질감들을 하나의 지도로 합하고 같은 재료(material)을 사용하기 위한 다수의 오브젝트를 만드는 것은 비용을 줄이므로, 권유합니다!

게임을 빠르게 하기 위한 간단한 체크리스트

  • 내장 쉐이더를 사용한다면, Mobile 카테고리를 살펴보세요. Mobile/VertexLit 는 현재 가장 빠른 쉐이더입니다.
  • 장면당 다른 재료(material)의 개수를 낮게 유지하세요- 가능하면 다른 오브젝트들 사이에서 더 많은 재료를 공유하세요.
  • 내부 최적화를 위해서 움직이지 않는 오브젝트들에게 Static 속성을 설정하세요.
  • 가능한 질감들을 위해서는 ETCI 포맷을 사용하세요. 아니면, 32bit 대신 16bit 질감을 선택하세요.
  • mipmaps를 사용하세요.
  • 통합기(combiners)또는 픽셀 쉐이더를 사용하세요. 이는 다중 패스 접근법 대신에 부분당 몇몇 질감을 혼합하기 위함입니다.
  • 사용자 설정 쉐이더를 작성시에는, 항상 가장 작은 부동 소수점을 사용하세요:
    • fixed / lowp -- 칼라와 라이팅 정보, 법선들을 위해서는 완벽합니다,
    • half / mediump -- 질감 UV 좌표들을 위해서 쓰입니다,
    • float / highp -- 픽셀 쉐이더에서는 피합니다. 정점 쉐이더에서 정점 위치 계산을 위한 사용에 괜찮습니다
  • 픽셀 쉐이더에서 복잡한 수식 연산(pow, sin, cos등)을 최소화 합니다.
  • 필요하지 않으면 Pixel Lights 는 쓰지 않습니다. – 기하에 영향을 주는 (가능한 방향성의) 하나의 픽셀 라이트를 선택하세요.
  • 필요하지 않으면 동적 라이트를 사용하지 않습니다 – 베이크 라이트를 대신 선택하세요.
  • 부분당 (per fragment) 더 작은 질감을 사용하세요.
  • 알파 테스팅을 피하세요. 알파 블렌딩(alpha-blending)을 대신 사용하세요
  • 필요하지 않으면 안개를 사용하지 마세요.
  • 폐색 누락(Occlusion culling) 의 장점을 알아보시고, 복잡한 정적 장면에 많은 폐색이 있을 시에는 가시 기하와 그리기 호출의 양을 줄이기 위해서 사용하세요. 폐색 누락으로부터 어떤 이득의 단계를 얻을 것인지 계획하세요.
  • 원거리 기하를 “위장(fake)” 위해서는 스카이박스(skybox)들을 사용하세요.

더 살펴보기

Posted by 프리랜서 디자이너
TA/Unity2013. 9. 9. 17:33

출처 : http://blog.naver.com/dfsin2/100188770656

 

최근에 모바일 프로젝트를 진행하면서 최적화에 대해 많은 필요성을 느끼게 되었습니다.

유니티 모바일 및 스크립트 관련해서 최적화 관련 부분을 하나씩 포스팅 해나갈까 합니다.

출처 : http://unitykoreawiki.com/index.php?n=KrMain.iphone-Optimizing-Scripts

스크립트 성능 최적화

이 페이지는 iOS에서 어떻게 스크립트 성능을 향상시킬수 있는지에 대한 일반 힌트를 제공합니다.

감소된 고정 델타 타임

15-25fps의 고정 델타 타임을 사용하세요. 사용자는 Edit->Project Settings->Time에서 이것을 바꿀수 있습니다. 이것은 FixedUpdate가 불리고 물리 엔진이 충돌감지(collision detection)와 rigidbody 업데이트하는 빈도수를 줄여줍니다. 주요 캐릭터에 rigidbody를 사용한다면 Rigidbody컴포넌트에서 낮은 고정 델타 타임 스텝을 부드럽게하기 위해 interpolation을 활성화 할 수 있습니다.

GetComponent콜수 줄이기

GetComponent나 BuiltIn 컴포넌트를 액세서를 사용하는 것은 주목할만한 오버헤드를 생기가 할 수 있습니다. 이것은 컴포넌트의 직접적인 참조를 캐싱하여 줄일수 있습니다.

예를 들어:

function Update () {
    transform.Translate(0, 1, 0);
}

대신 아래와 같이 최적화 할수 있습니다:

myTransform : Transform;
function Awake () {
   myTransform = transform;
}
function Update () {
    myTransform.Translate(0, 1, 0);
}

 >> 직접 gameObject 나 transform 과 같은 BuiltIn 컴퍼넌트의 사용을 자제하고

변수로 만들어서 사용하라는 의미인거 같네요.


메모리 할당을 피하세요

  • 스크립트에서 할당을 최소화하세요.
  • Structs를 사용하세요. Structs는 메모리를 할당하지 않습니다. 대신 스택에 놓이게되며 값으로 전달을하며 이것이 더 빠릅니다.

GUI 를 줄이세요

  • GUILayout대신 GUI functions을 사용하고 화면에서 GUI의 양을 최소화 하세요
  • GUI 오버헤드를 줄이기 위해MonoBehaviour.useGUILayout = false를 사용하세요
function Awake () {
    useGUILayout = false;
}

>> 그냥 유니티 내장 GUI를 안 쓰는게 답입니다...

    에셋 스토어에서 판매하는 GUI 플러그인 (EZGUI 및 NGUI) 등을 구매하셔서 사용하는게 좋을듯 하네요.
    불가피하게 내장 GUI를 써야 한다면 저런 방법도 좋겠네요.

iOS 스크립트 콜 최적화를 사용하세요

UnityEngine 내임스페이스에 있는 대부분의 함수는 C/C++로 구현되어 있습니다. 그런 함수를 스크립트에서 부르는 것은 성능에 추가적인 오버헤드가 있습니다. 프레임당 추가의 몇 밀리세컨드를 얻기 위해서는 Edit->Project Settings->Player 에 있는 iOS스크립트 콜 최적화를 사용하세요:

  • Slow and Safe - 기본적인 단일의 내부 콜 핸들링 (익셉션 지원함) .
  • Fast and Exceptions Unsupported - 빠른 단일 내부 콜 구현, 그러나 익셉션이 지원되지 않으므로 조심히 사용하세요. 이것이 유용한 전형적인 경우:프로그램이 유니티엔진을 많이 사용하면서 익셉션이 생기지 않을때 입니다. 이 옵션은 1-4ms/frame을 줄일 수 있습니다.

>> 올ㅋ 요건 몰랐네 한번 써봐야겠다.


Garbage Collection 최적화

  • 위에 서 말한 것처럼 어떤 할당도 피하도록 하세요
  • 만약 피할수 없다면 두가지 할당/수집 방법이 있습니다:
    • 작은 힙 빠르고 자주 일어나는 가비지 콜렉션 전략
      이 방법은 아주 긴 액션 게임플레이가 있고 부드러움 framerate가 필요한 게임에서 잘 작동합니다.
      짧은 시간동안 작은 블락을 할당하는 유니티 iOS게임에서 힙은 보통 ~5ms(iPhone 3G에서)걸립니다. 1MB힙에서는 가비지 컬력션은 ~7ms정도 더 걸립니다.
      가끔은 매 N번 프레임마다 강제 가비지 콜렉션을 하는것도 유용합니다:
if (Time.frameCount % 30 == 0)
{
   System.GC.Collect();
}
  • 그러나 유의해서 사용하세요. 내부 프로파일러 통계를 보고 그것을 바탕으로 결정을 내리세요.
  • 큰 힙 느리고 빈도수가 낮은 가비지 콜렉션
    이 방법은 게임이 요구하는 부드러운 프레임 속도가 짧은 것과 중간 사이의 길이일 때 사용을 합니다. 아이디어는 게임이 실행될때는 가비지 컬렉션을 피하고 게임이 중단 되었을 때하는 것입니다. 게임 시작에 힙에 어느 정도의 공간을 미리 할당하는 것도 좋은 생각인데 그 공간은 게임 플레이 세션이 잘 돌아갈수 있을 만큼 크고 OS의 낮은 메모리 시스템으로 인해 프로그램이 멈추지 않을 만큼의 작은 공간을 말합니다. 모노는 필요할 때문 힙을 늘리기 때문에 가끔 시작시에 강제적으로 확장하는 것도 좋은 생각입니다:
function Start() {
 var tmp = new System.Object[1024];
 // 할당은 작은 블락에해서 큰 블락은 위하 특별한 처리 방법을 피하도록 합니다
        for (var i : int = 0; i < 1024; i++)
  tmp[i] = new byte[1024];
 // 참조를 풀어 줍니다
        tmp = null;
}

나중에 게임 플레이가 중단 되었을때 강제적으로 가비지 콜렉션을 할 수 있습니다:

System.GC.Collect();

주의해서 사용하셔야 합니다. 내주 프로파일러 통계에 주목하시고 실제 숫자를 바탕으로 결정을 내리세요.

 

>> 가비지 컬렉터 주의해서 사용해야죠.

    저희는 주기적으로 (며느리도 안알려줌) GC.Collect 를 호출하는데

    요때 부하가 좀 걸리게 됩니다. 고려하시고 사용해야할듯...

 

Posted by 프리랜서 디자이너
TA/Unity2013. 9. 5. 14:51

어이없지만 자꾸 잊어 버린다... 하아~

 

문자 -> 숫자 =      int.Parse()

숫자 -> 문자 =     .ToString()

Posted by 프리랜서 디자이너
TA/Unity2013. 8. 29. 14:39

유니티게임 구글 인앱 결제 붙이기!!d Unity

2013/03/11 19:16

복사 http://blog.naver.com/psd0217/10162792878

전용뷰어 보기

1. 먼저 만들어진 유니티게임을 빌드 하여 APK파일을 만들어서 구글 플레이 개발자 콘솔 사이트 들어가서 어플을 등록해 주세요~!

물론 여기까지 들어오려면 개발자 등록을 해야 한다.

돈이 듭니다...ㅠㅠ

우선 매인은 이게 아니니까 패스 하고

새 애플리케이션 추가 클릭 클릭

 

이런화면이 뜨는데 1번 에 당연히 어플이름을 적어주시면 되고

APK업로드 누르시면 업로드가 됩니다.

 

여기서도 잠깐 업로드가 안된다고요??

그렇다면 유니티 빌드할때 키를 넣지 않았다는 뜻인데요

이것도 인터넷 쪼금만 찾아보면 나오는 것이니까 패스 할게요~!

 

자!! 여기서 궁금증?? 왜 인앱 시스템을 집어 넣지도 않았는데 어플을 업로드 했나요??

그건 밑에 설명해 드릴께요 차근차근 합니다

 

아 그리고 업로드 한다고 바로 어플 다운이 되고 구글 플레이에서 검색이 되고 이러는거 아니니까 걱정 마세요

어플 활성화 버튼을 누르지 않는 이상 어플은 완전히 등록 된것이 아니기 때문에 상관 없습니다.

 

자 다음은~유니티로 돌아가서~~

 

이부분은 다들 아시겠죠???

파일 -> 빌드 셋팅 -> 플레이어 셋팅

을 하시면~ 밑에처럼

이렇게 나오죠 ㅋㅋ

당연히 빌드를 했다면 저기 번들 이름을 지정하셧겟죠???

이거 복사 해 두세요~! ㅋ

 

자 다음은 이클립스에서 안드로이드 프로젝트를 생성해 볼까요?

자 프로젝트를 생성하다보면 패키지 이름을 지정하라고 나오죠???

방금 유니티에서 복사한 번들 이름 집어 넣어 주세요

자자 다음은 

생성된 프로젝트에서 오른쪽 마우스 클릭

그리고 properties를 눌러 주세요~!

이런화면이 나오는데 순서대로 눌러 주세요~!


자 그럼 저 파일을 찾아야 하는데 어딧을까요??ㅋ

경로는 Program File->Unity->Editor->Data->PlaybackEngines->androidplayer->bin

이경로에 있습니다 ㅋ

없다고요?? 그럴리가

유니티가 설치되어 있다면 당연히 있어야 정상입니다

없으면...구글링 혹은 유니티 재설치 ㄱㄱ
무튼 열기를 누르면

이번에도 순서대로 누르시기만 하면 됩니다.



위처럼 프로젝트 안에 classes.jar파일이 생성 되었다면 완료~!

이로써 이클립스에서 유니티 함수들을 불러다 쓸수 있게 되었습니다~~~짝짝짝~!

끝낫냐고요???

아직 멀었으니 따라 오세요


자 그러면 다음은 아래의 파일을 다운받아서 압축 풀고 임포트를 시켜 주세요

BillingTest.zip

위 그림처럼 src폴더에 복사해 주세요

그리고 다시 구글 플래이 개발자 콘솔로 돌아와서

여기서 왜 인앱결제 시스템을 붙이지 않고 어플을 등록 시켰는지 이해를 하게 될거에요

왜냐면 위의 그림처럼 인앱시스템을 구축하려면 구글에서 주는 키를 등록해 주어야 하는데

이 소스에서는 이부분을 소스 코드 안에서 처리를 해주기 때문이죠~! ㅋ

위 소스를 복사해서~

조기에 붙여넣어 주세요

잘 안보이시나???

babyaba.Test.billing 밑에 있는Security 클래스에 base64EncodedPublicKey부분에 붙여 넣어주시면 됩니다

 

그림으로는 안나와 있지만 MainActivity 소스를 아래처럼 바꿔 줍니다

 

 

 

 

 

import bayaba.test.billing.BillingService;

import bayaba.test.billing.Consts;

import bayaba.test.billing.PurchaseObserver;

import bayaba.test.billing.ResponseHandler;

import bayaba.test.billing.BillingService.RequestPurchase;

import bayaba.test.billing.BillingService.RestoreTransactions;

import bayaba.test.billing.Consts.PurchaseState;

import bayaba.test.billing.Consts.ResponseCode;

import com.Bumblebee.CatsIsland.MainActivity;

 

import com.unity3d.player.UnityPlayer;

import com.unity3d.player.UnityPlayerActivity;

 

import android.os.Bundle;

import android.os.Handler;

import android.os.Message;

import android.app.AlertDialog;

import android.content.DialogInterface;

 

public class MainActivity extends UnityPlayerActivity {

 

    private GamePurchaseObserver mPurchaseObserver;

    private Handler mHandler;

    private BillingService mBillingService;

  

    private class GamePurchaseObserver extends PurchaseObserver

    {

        public GamePurchaseObserver(Handler handler) {

            super(MainActivity.this, handler);

        }

 

@Override

public void onBillingSupported(boolean supported, String type){

if (type == null || type.equals(Consts.ITEM_TYPE_INAPP)) {

if (supported) {

mBillingService.restoreTransactions();

}

}

}

 

        @Override

        public void onPurchaseStateChange(PurchaseState purchaseState, String itemId, int quantity, long purchaseTime, String developerPayload)

        {

        switch (purchaseState)

        {

case PURCHASED:

UnityPlayer.UnitySendMessage("AndroidManager", "CharacterPurchaseState", itemId );

// 현재 구매 확인

break;

case CANCELED:

//UnityPlayer.UnitySendMessage("AndroidManager", "LabelLog", "CANCELED" + itemId );

// 취소 ..

break;

/*

case REFUNDED:

UnityPlayer.UnitySendMessage("AndroidManager", "LabelLog", "REFUNDED" + itemId );

// 환불 ..

break;

*/

default:

break;

}

        }

 

        @Override

        public void onRequestPurchaseResponse(RequestPurchase request, ResponseCode responseCode)

        {

            if (responseCode == ResponseCode.RESULT_OK) 

            {

            // 확인 메시지

            UnityPlayer.UnitySendMessage("AndroidManager", "PurchaseResult", "ok" );

            // 확인된 아이템 아이디

            UnityPlayer.UnitySendMessage("AndroidManager", "PurchaseOk", "" + request.mProductId );

           

            if (Consts.DEBUG) 

            {

                    //Log.i(TAG, "purchase was successfully sent to server");

                }

            }

            else if (responseCode == ResponseCode.RESULT_USER_CANCELED) 

            {

            // 취소 메시지

            UnityPlayer.UnitySendMessage("AndroidManager", "PurchaseResult", "cancle" );

            // 취소된 아이템 아이디

            UnityPlayer.UnitySendMessage("AndroidManager", "PurchaseCancle", "" + request.mProductId );

           

                if (Consts.DEBUG) 

                {

                    //Log.i(TAG, "user canceled purchase");

                }

            } 

            else 

            {

                if (Consts.DEBUG) {

                    //Log.i(TAG, "purchase failed");

                }

            }

        }

 

        @Override

        public void onRestoreTransactionsResponse(RestoreTransactions request, ResponseCode responseCode)

        {

        if (responseCode == ResponseCode.RESULT_OK)

        {

// Log.d(TAG, "completed RestoreTransactions request : " + request.getStartId());

}

        else 

        {

// Log.d(TAG, "RestoreTransactions error: " + responseCode);

}

        }

    }

    

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

        

        InitBiling();

}

private void InitBiling()

{

    mHandler = new Handler();

 

    mPurchaseObserver = new GamePurchaseObserver(mHandler);

        mBillingService = new BillingService();

        mBillingService.setContext(this);

        

        ResponseHandler.register(mPurchaseObserver);

        if ( !mBillingService.checkBillingSupported() )

   {

        //showDialog(DIALOG_CANNOT_CONNECT_ID);

  }

}

public void BuyItem( String item_name )

{

if ( !mBillingService.requestPurchase(item_name, Consts.ITEM_TYPE_INAPP, "REQUEST_PURCHASE") )

{

UnityPlayer.UnitySendMessage("AndroidManager", "LabelLog", "PurchaseError");

}

}

//public void initActivity(String tagFromUnity, String messageFromUnity)

    //{

    // UnityPlayer.UnitySendMessage("AndroidManager", "AndroidLog", "[" + tagFromUnity + "]" + messageFromUnity);

    //}

public void quitApplication()

    {

handler.sendEmptyMessage(0);

    }

public Handler handler = new Handler()

{

public void handleMessage(Message msg)

{

switch(msg.what)

{

case 0:

finishMessage();

}

}

};

public void finishMessage()

{

AlertDialog.Builder builder = new AlertDialog.Builder(this);

builder.setMessage("프로그램을 종료 하시겠습니까?");

builder.setCancelable(false);

builder.setPositiveButton("예", new DialogInterface.OnClickListener() {

@Override

public void onClick(DialogInterface dialog, int which)

{

UnityPlayer.UnitySendMessage("AndroidManager", "ApplicationQuit","");

}

});

builder.setNegativeButton("아니요", new DialogInterface.OnClickListener(){

@Override

public void onClick(DialogInterface dialog, int which)

{

dialog.cancel();

}

});

builder.show();

}

@Override

public void onDestroy()

{

super.onDestroy();

mBillingService.unbind();

}

   

@Override

protected void onStart() {

super.onStart();

ResponseHandler.register(mPurchaseObserver);

}

 

@Override

protected void onStop() {

super.onStop();

ResponseHandler.unregister(mPurchaseObserver);

}

 

}




이 클래스로 유니티와 함수 호출을 왔다갔다 해줍니다.


 


이대로 프로젝트를 익스포트 해주시구요

 

jar파일을 선택해서

1번 처럼 체크를 해주시고 

2번처럼 경로와 파일이름을 지정해 주시고

finish!!!

이로서 플러그인 완전 완성~!!!!!

안된다구요??

끝~!!!! 이었으면 좋았으나 아직 좀 남았습니다~!

다시 유니티로 돌아와서

빌드를 해주시는데~

이미 빌드했다면 안해 줘도 됨 ㅋ

프로젝트 경로로 쭉쭉 들어가서 Temp폴더를 살펴 보시면 위 폴더가 보일거에요~!

다 필요 없고

그안에 있는 매니 패스트만 복사 해서 다른 폴더에 넣어주세요

아까 생성한 jar파일 있는곳에 같이 넣어주면 좋구요

자 다시 유니티에서 Plugins 폴더와 Android폴더를 만들어서 그 밑에

두파일을 집어 넣어 주세요

위 경로는 무조건 저렇게

한글자라도 틀리면 못읽어 오니까 주의 하시구요~!!!

 

그리고~! 매니페스트 파일을 열어 보시면

밑에 처럼 뭐라뭐라 솰랴 솰랴 하는데

다 필요 없고요

1번 젤위 의 페키지 명을 플러그인으로 가져온(이클립스에서 가져온) jar파일에있는 패키지명..com.어쩌고.어쩌고 했던 그거 적어 주세요~!

2번 부분에는 3번에 있는 MAIN이랑 LANCHER 이부분이 있을탠대요 싹 지워 주세요

이유는 뭐랄까 저부분은 다른 패키지 명으로 열어줘야 해서?? 라고 답해드리죠  매인이 두번 올순 없으니까요

3번은 그냥 그대로 적어주세요

대략 내용은 위에서 지운 매인부분 넣어주고 결제 시스템 클래스들을 같이 써주기 위함이죠

아 그리고 깜빡하고 위의 그림에서 그리지 않은 부분이 있는데요

<uses-permission android:name="com.android.vending.BILLING"/>

그림 밑에 쪽에 보시면 이 소스 보이시죠

꼭 써줘야 결제가 됩니다~!!!

 

다시 유니티로 돌아와서~!!!

 

 

위 처럼 안드로이드매니져 클래스를 만들어 주세요

당연 클래스 이름 저거랑 같아야 됩니다. 왜냐면 아까 이클립스에서 호출하는 클래스 이름을 저걸로 해뒀거든요 쭉 살펴 보시면 아실거에요

이 클래스에는

 

 

using UnityEngine;

using System.Collections;

 

public class AndroidManager : MonoBehaviour

{

    private static AndroidManager _instance;

 

    public string androidLog = "No Log";

public string fps = "No fps";

public string purchaseOkItemID = "";

public string purchaseCancleItemID = "";

public bool character2State = false;

public bool character3State = false;

public bool character4State = false;

public bool character5State = false;

public bool purchaseOk = false;

public bool purchaseCancle = false;

 

//#if UNITY_ANDROID && !UNITY_EDITOR

 

    public AndroidJavaObject activity;

 

    void Awake()

    {

 

        AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");

        activity = jc.GetStatic<AndroidJavaObject>("currentActivity");

    }

 

//#endif

 

void OnGUI()

{

GUI.Label( new Rect( 10, 10, 200, 20 ), "fps : " + fps );

GUI.Label( new Rect( 10, 30, 600, 20 ), "" + androidLog );

GUI.Label( new Rect( 10, 50, 600, 20 ), "character2State : " + character2State );

GUI.Label( new Rect( 10, 70, 600, 20 ), "character3State : " + character3State );

GUI.Label( new Rect( 10, 90, 600, 20 ), "character4State : " + character4State );

GUI.Label( new Rect( 10, 110, 600, 20 ), "character5State : " + character5State );

GUI.Label( new Rect( 10, 130, 600, 20 ), "purchaseOk : " + purchaseOk );

GUI.Label( new Rect( 10, 150, 600, 20 ), "purchaseCancle : " + purchaseCancle );

}

public void Buy( string ItemID )

{// 이클립스에서 작성한 클래스에서 BuyItem함수를 호출하는겁니다. 물론 뒤에는 인자값임

activity.Call("BuyItem", "" + ItemID );

}

public void Exit()

{// 위와 같이 함수를 호출하는거입니다

activity.Call("quitApplication");

}

// 이 밑에 부분은 신경 안쓰셔도 되고 쓰셔도 되고

// 대강 설명하자면 이클립스에서 만든 클래스에서 불려 쓰이는 함수들입니다.

 

void PurchaseOk( string ItemID )

{// 현재 무슨 아이템이 구매가 되었는지를 알아오는함수

purchaseOkItemID = ItemID;

}

void PurchaseCancle( string ItemID )

{// 현재 무슨 아이탬이 취소가 되었는지 알아오는 함수

purchaseCancleItemID = ItemID;

}

void PurchaseResult( string result )

{// 현재 아이템을 결재 했는지 취소했는지 알아오는함수

if( "ok" == result )

{

purchaseOk = true;

}

else if( "cancle" == result )

{

purchaseCancle = true;

}

}

void CharacterPurchaseState(string itemID)

{// 현재까지 결재된 아이템이 무었인지 알려주는 함수 (당연히 수정해서 쓰시겟죠?)

if( "character2" == itemID )

{

character2State = true;

}

if( "character3" == itemID )

{

character3State = true;

}

if( "character4" == itemID )

{

character4State = true;

}

if( "character5" == itemID )

{

character5State = true;

}

}

void ApplicationQuit(string message)

{// 이함수가 불리는순간 게임 종료

Application.Quit();

}

void LabelLog(string message)

{// 에러 매시지 같은 로그를 받아옵니다. 

// 인앱부분은 핸드폰 기기에서만 사용할수 있기 때문에 애러같은것을 라벨로 로그를 남겨줌

androidLog = "Log : " + message;

}

// 당연 어떤 클래스에서 불릴수 있는 싱글톤의 매력~!!!

    public static AndroidManager Instance

    {

        get

        {

            if (_instance == null)

            {

                _instance = FindObjectOfType(typeof(AndroidManager)) as AndroidManager;

                if (_instance == null)

                {

                    _instance = new GameObject("AndroidManager").AddComponent<AndroidManager>();

                }

            }

 

            return _instance;

        }

    }

}

 

대략 요딴식으로 적어주시면 되는대요

설명은 주석으로 달려있으니까 확인해 보세요

결재 되는 부분(클래스 or 함수)에서

AndroidManager.Instance.Buy( _itemID );

이런식으로만 써주면 바로 결재 들어갑니다.ㅋㅋ

 

자 다음은 다시 구글 플래이 게발자 콘솔로 돌아와서

인앱제품 부분으로 들어가서

새 제품 추가를 하시면~~~


 

위 그림처럼 나오는데요

관리되는 제품 관리되지 않은 제품으로 나뉘게 됩니다.

뭐 인터넷 조금만 확인해 보시면 되실꺼지만

관리되는 제품은 구글 서버에서 이아이템을 가지고 있는지 아닌지를 알아서

단 한번만 제품을 구매하게끔 만들어 줍니다.

관리되지 않는 제품은 

예를 들면 게임에서 게임머니같은 건대요

여러번 구매 할수 있습니다.

제품ID는 자신이 짠 소스 itemID와 일치 시켜야 합니다

뭐 간단한 설명과 아이템 이름을 적어주고

활성화를 시켜줍니다.

 

이렇게 모든게 끝이 났습니다.

그러면 다시 유니티 빌드를 해주시고

구글 콘솔에 APK파일을 다시 업로드 해주시고(당연히 전버전과는 버전코드와 번호가 달라야 올라가겠죠??)

테스트 아이디도 입력해 주시고~!!!(이 아이디는 테스트 대상자 폰의 구글 계정과 일치 해야 합니다.)

테스트 아이디는 개발자 콘솔 왼쪽에 설정 누르면 나옵니다~!!!!

두세시간후에 구매를 해보시면~!!

짜잔 결제가 됩니다~!!!!

물론 진짜로 결제 되 버림 ㅠㅠㅠ

이거 환불 받으세요 이부분은 인터넷 참조해 주쌔요~!ㅋㅋㅋㅋ

 

 

Posted by 프리랜서 디자이너
TA/Unity2013. 8. 29. 14:29

유니티 페이스북 연동 - 안드로이드(로그인&아웃,내사진&글 올리기&정보,친구목록) Unity

2013/06/10 15:56

복사 http://blog.naver.com/psd0217/10170072555

전용뷰어 보기

이번 포스팅은 유니티3D 네이티브 안드로이드에 페이스북 SDK 연동을 정리해봅니다. 원래는 Facebook SDK for .NET으로 연동할까 했는데 추후에 시간이 있을 때 다시 해볼까 합니다. 포스팅 많이하기 시작했던 cocos2d-x 때와는 다르게 하나에 쭉 다 포스팅이 아닌 먼저 포스팅했던 내용들은 그 링크들로 대신합니다.
  • 페이스북 개발자 및 앱 등록
  • 유니티3D 안드로이드 JAR 플러그인 프로젝트 생성
  • 페이스북 SDK 설치 및 빌드
  • 연동에 필요한 관련 파일 복사 및 AndroidManifest.xml 수정
  • 테스트를 위한 페이스북 해시키 생성 및 등록
 위와 같은 내용들을 준비과정으로 정리했습니다.


1. 페이스북 개발자 등록

 먼저 페이스북 개발자 등록을 합니다.


2. 페이스북 앱 등록

 만들어 서비스할 앱을 페이스북에 등록합니다.


3. 유니티3D 프로젝트 및 안드로이드 페이스북 Jar 플러그인 만들기

 유니티3D에서 안드로이드용 외부 SDK 연동을 위해서는 플러그인 JAR 파일을 만들어야하죠. 링크에 있는 내용을 보시고 폴더 설정등 기본 준비작업을 하시면 됩니다. 저는 스샷과 같이 UnityAndroidFacebookJar라고 만들었습니다.


4. 페이스북 안드로이드 SDK 설치 및 임포트

 페이스북 개발자 페이지의 안드로이드 SDK를 다운로드합니다. v3.0.1이 현재 최신입니다.

 적당한 곳에 다운로드 받은 페이스북 안드로이드 SDK를 압축해제합니다. 제 프로젝트 구성은 위와 같습니다. UnityFacebook은 유니티3D 프로젝트고 AndroidJar에는 위에서 생성한 이클립스 프로젝트가 들어있습니다.

 이클립스에서 페이스북 SDK를 임포트합니다. facebook-android-sdk-3.0.1\facebook 에 들어있습니다. 그러면 스샷과 같이 느낌표가 있고 에러가 발생할 듯합니다.

Project 'FacebookSDK' is missing required source folder: 'gen'
The project cannot be built until build path errors are resolved
Unable to resolve target 'android-8'

 위와 같은 에러인데 따로 정리를 했으니 링크를 참고하시기 바랍니다.

 이제 안드로이드 JAR 프로젝트에서 페이스북 SDK를 스샷과 같이 Library로 추가해줍니다. 그러면 Jar mismatch! Fix your dependencies 에러가 발생합니다. android-support-v4.jar가 중복되서 발생한 문제로 링크에 정리해놨습니다.

 이제 페이스북 SDK를 빌드합니다.


5. 페이스북 SDK 및 Res 복사

 유니티3D Plugins\Android 디렉터리에 페이스북 SDK의 bin 디렉터리에 생긴 facebooksdk.jar파일과 libs에 있는 android-support-v4.jar 파일을 복사합니다. android-support-v4.jar를 복사하지 않으면 나중에 java.lang.NoClassDefFoundError: android.support.v4.content.LocalBroadcastManager 에러가 발생할 수 있습니다.

 AndroidManifest와 UnityAndroidFacebook.jar는 위에서 만든 이클립스 프로젝트의 것을 복사했습니다.

 페이스북 SDK의 res 디렉터리를 마찬가지로 복사해줍니다. 역시나 res를 복사하지 않으면 android.content.res.Resources$NotFoundException: Resource ID #0x7f030001 에러가 발생합니다.


6. AndroidManifest.xml 수정

<uses-permission android:name="android.permission.INTERNET" />

        <activity
            android:name="com.facebook.LoginActivity"
            android:label="@string/app_name" />

 페이스북을 위해 AndroidManifest.xml에 위와 같은 내용을 추가합니다. Resource re-package failed 에러에 대비해서 drawable/ic_launcher을 drawable/app_icon 으로 바꾸는 것도 잊지마시기 바랍니다.


7. 페이스북 해시키 생성 및 등록

 페이스북을 연동한 안드로이드 앱을 테스트하려면 페이스북 개발자 페이지에서 등록한 앱에 해시키 값을 위 스샷과 같이 등록해야합니다. 해시키 생성하는 것은 따로 정리 했으니 링크를 참고하시고 만들어진 해시키를 각자가 만드신 앱의 정보 페이지에서 네이티브 Android 앱 부분을 클릭해 Key Hashes 부분에 기입하신 후 변경 내용 저장하면 됩니다.

 다음 포스팅에서는 페이스북 SDK 초기화와 로그인, 로그아웃 코드 연동 작업을 정리하겠습니다.

 

 

 

 

 

 

 

 

 

 

 

 유니티3D 안드로이드 프로젝트에 페이스북 연동을 위한 준비작업을 정리했었습니다. 이번에는 위 링크 내용을 기준으로 페이스북 초기화부터 로그인, 로그아웃 연동 작업에 대해 정리해봅니다.

 Prime31이라는 곳에서 각종 플러그인을 유료로 팔고 있네요. 그중에 당연히 페이스북 플러그인도 있긴합니다. 제가 정리하는건 Prime31이 필요없는 직접 구현하는 것에 대한 정리입니다. 즉, without Prime31 이죠. 아래는 소스입니다.

1. Android

public class MainActivity extends UnityPlayerActivity {
///< 페이스북 앱 등록용 해시키값
private String strHash;
///< 페이스북에 등록한 앱 ID
private String strAppId;
///< 인스턴스 상태 값
private Bundle savedInstanceState;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
///< 인스턴스 상태를 저장한다.
this.savedInstanceState = savedInstanceState;
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
Session.getActiveSession().onActivityResult(this, requestCode, resultCode, data);
super.onActivityResult(requestCode, resultCode, data);
}

protected void onSaveInstanceState(Bundle outState) {
Session session = Session.getActiveSession();
Session.saveSession(session, outState);
super.onSaveInstanceState(outState);
}

///< 페이스북 초기화. 유니티에서 호출하는 함수
public void InitFacebook_U(String strAppId)
{
this.strAppId = strAppId;

///< 해쉬키를 찾는다. 패키지 이름은 각자 다를것이다.
try {
PackageInfo info = this.getPackageManager().getPackageInfo("com.Test.unityandroidfacebookjar", PackageManager.GET_SIGNATURES);
for (Signature sig : info.signatures) {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(sig.toByteArray());
strHash = Base64.encodeToString(md.digest(), Base64.DEFAULT);
}
}
catch (NameNotFoundException e) {
Log.d("UnityFacebookTest", "Error Hashkey not found");
}
catch (NoSuchAlgorithmException e) {
Log.d("UnityFacebookTest", "Error Hashkey no such algorithm");
}
///< 해시키를 출력. 이 값을 페이스북 개발자 센터의 등록한 앱에 기입
Log.d("UnityFacebookTest", "Hash : " + this.strHash);

Session session = Session.getActiveSession();
///< 세션이 없다면 생성을 하자.
if (session == null) {
///< 세션 복구 시도
if (this.savedInstanceState != null) {
session = session.restoreSession(this, null, statusCallback, this.savedInstanceState);
Log.d("UnityFacebookTest", "Session restoreSession");
}
///< 세션 생성
if (session == null) {
session = new Session.Builder(this).setApplicationId(this.strAppId).build();
Log.d("UnityFacebookTest", "Session Builder");
}

///< 세션 저장하고 오픈
Session.setActiveSession(session);
if (session.getState().equals(SessionState.CREATED_TOKEN_LOADED)) {
session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
Log.d("UnityFacebookTest", "Session openForRead");
}
}
}

///< 로그인. 유니티에서 호출하는 함수
public void Login_U() {
     Session session = Session.getActiveSession();
     if (session.isOpened() == false && session.isClosed() == false) {
     session.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
     Log.d("UnityFacebookTest", "Login openForRead");
     } else if (session != null) {
     Session newSession = new Session.Builder(this).setApplicationId(this.strAppId).build();
     Session.setActiveSession(newSession);
     newSession.openForRead(new Session.OpenRequest(this).setCallback(statusCallback));
     Log.d("UnityFacebookTest", "Login new Session");
     } else {
     Log.d("UnityFacebookTest", "Error Session is null");
     }
    }
///< 로그아웃
public void Logout_U() {
Session session = Session.getActiveSession();
if (session.isClosed() == false) {
session.closeAndClearTokenInformation();
Log.d("UnityFacebookTest", "Logout ClearTokenInfo");
}
}
///< 세션 처리 콜백
private Session.StatusCallback statusCallback = new SessionStatusCallback();
    private class SessionStatusCallback implements Session.StatusCallback {
        @Override
        public void call(Session session, SessionState state, Exception exception) {
            if (state.isOpened())
            {
                Log.d("UnityFacebookTest", "Session state opened");
            }
            else
            {
                Log.d("UnityFacebookTest", "Session state closed");
            }
        }
    }
}

 준비과정에서 만들었던 UnityAndroidFacebookJar 프로젝트의 MainActivity.java 소스를 위와같이 수정 및 저장하고 빌드 후 jar 파일로 export합니다. export된 jar 파일은 유니티 프로젝트의 플러그인 디렉터리에 복사해주시구요.

 지난번에는 페이스북 해시키 생성을 위해 콘솔에서 openssl도 설치하고 keytool로 추출을 하는 복잡한 과정을 거쳤는데 이번에는 위와같이 코드로 처리했습니다. 해당 소스는 처음 추출할 때만 필요하고 추출하셨다면 지우셔도 무관합니다.


2. Unity3D

public class FacebookManager : MonoBehaviour
{
static FacebookManager _instance;
private AndroidJavaObject curActivity;

public static FacebookManager GetInstance()
{
if( _instance == null )
{
_instance = new GameObject("FacebookManager").AddComponent<FacebookManager>();
}

return _instance;
}

void Awake()
{
AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
curActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");
}

public void Init(string strAppId)
{
curActivity.Call("InitFacebook_U", strAppId);
}

public void Login()
{
curActivity.Call("Login_U");
}

public void Logout()
{
curActivity.Call("Logout_U");
}
}

 간단한 FacebookManager 싱글턴 컴포넌트입니다. 이제 이것을 사용하는 TestGUI 컴포넌트는 아래와 같습니다.

public class TestGUI : MonoBehaviour
{
void Start()
{

}

// Update is called once per frame
void Update ()
{
if (Application.platform == RuntimePlatform.Android)
        {

            if (Input.GetKey(KeyCode.Escape))
            {
                Application.Quit();
                return;
            }
}
}

void OnGUI()
{
float fYpos = 0;
GUI.Label(new Rect(0, fYpos, 400, 100), "Unity3D Android Facebook Test");

fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Init") == true)
{///< 자신의 페이스북 앱 ID를 넣어준다.
FacebookManager.GetInstance().Init("442544649174747");
}

fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Login") == true)
{
FacebookManager.GetInstance().Login();
}

fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Logout") == true)
{
FacebookManager.GetInstance().Logout();
}
}
}

 페이스북 초기화, 로그인 등의 버튼을 만드는 GUI 컴포넌트입니다. Main Camera에 붙여줍니다.


3. Facebook R.java Build
 

 마지막으로 유니티에서 빌드한 후 임시 디렉터리인 Temp/StagingArea/gen/com/Test/unityandroidfacebookjar에 생성되는 Facebook의 R.java를 플러그인에 위 스샷과 같이 jar로 만들어 넣어줘야합니다. 그런데 이 부분에서 java.lang.NoClassDefFoundError: com.facebook.android.R$layout 이슈가 있습니다. 이슈 해결은 링크에도 있지만 완벽한 해결이 아니라는게 좀 걸리네요. 페이스북 SDK 버전이라도 올라간다면 나중에 또 이슈가 생길 수 있습니다.


4. Build and Run
 

 빌드하고 에이서 A500에서 실행한 스샷입니다.
 

 Init을 눌러 Facebook을 초기화 한 후 Login을 누르면 위와같이 페이스북 로그인 페이지가 뜹니다. 참고로 전 이 테스트를 위해 태블릿에 깔린 페이스북 앱에서 로그아웃을 한 후 진행했습니다. 이미 로그인이 된 상태라면 조금 다를 수 있습니다. 아마 바로 로그인 되거나 잠깐 로딩 화면이 나오고 다시 유니티 화면으로 전환될 것입니다.
 

 로그인이 되면 위와같이 UnityFacebook에서 공개 프로필, 친구 리스트에 액세스 권한을 요청하고 있습니다. 라고 뜹니다. 확인을 눌러줍니다.

 이것으로 유니티3D에 페이스북 SDK 안드로이드 연동 기본사항을 정리해봤습니다. 다음에는 자신의 담벼락에 게시하는 것과 자신의 정보를 얻어와 프로필 사진을 출력해보는 것을 정리해보겠습니다.

 

 

 

 

 

 

 

 

 유니티3D 안드로이드에 페이스북 초기화, 로그인 로그아웃 연동을 정리했었습니다. 이번에는 아래와 같은 것들을 정리해봅니다. 

  • 자신의 정보를 얻기
  • 자신의 담벼락에 글을 게시
  • 자신의 프로필 사진 이미지 출력

1. 자신의 담벼락에 글 게시

public void PostToMeWall_U(final String strMsg) {
runOnUiThread(new Runnable(){
public void run() {
Session session = Session.getActiveSession();
final List<String> PERMISSIONS = Arrays.asList("publish_stream");
if (session != null)
{
NewPermissionsRequest reauthRequest = new Session.NewPermissionsRequest(UnityPlayer.currentActivity, PERMISSIONS);
session.requestNewPublishPermissions(reauthRequest);
}

Bundle postParams = new Bundle();
postParams.putString("message", strMsg);

        Request request = new Request(session, "/me/feed", postParams,
                              HttpMethod.POST, requestCallback);
       
        RequestAsyncTask requestAsyncTask = new RequestAsyncTask(request);
        requestAsyncTask.execute();
}
});
}

 유니티에서 호출하는 자바 함수입니다. publish_stream 권한은 사실 자신의 담벼락에 게시할 때는 필요하지 않은 듯합니다. 자신 이외에 친구들에게 할 때 필요한 듯보이네요. graph api중 하나에 속하는 message를 추가하고 유니티로부터 받은 스트링을 추가합니다. 요청할때는 /me/feed 라고 했는데 밑에서 알아볼 자신의 숫자로된 페이스북 id를 넣어줘도 됩니다. 친구의 id를 넣어주면 친구의 담벼락에 게시가 되겠죠.

Request.Callback requestCallback = new Request.Callback() {
      public void onCompleted(Response response) {
          JSONObject graphResponse = response.getGraphObject().getInnerJSONObject();

          String postId = null;

          try {
              postId = graphResponse.getString("id");
          } catch (JSONException e) {
              Log.i("UnityFacebookTest", "JSON error " + e.getMessage());
          }

          FacebookRequestError error = response.getError();

          if (error != null) {
           Log.d("UnityFacebookTest", error.getErrorMessage());
          } else {
           Log.d("UnityFacebookTest", "success post score to wall. " + postId);
          }
      }
};

 요청에 대한 콜백입니다. 로그 정도만 처리하고 있습니다.


public string strPostMsg = string.Empty;

public void PostToMeWall(string strMsg)
{
curActivity.Call("PostToMeWall_U", strMsg);
}

 FacebookManager 컴포넌트의 추가된 내용입니다. 스트링 변수를 하나 추가해주고 자바 호출을 추가해줍니다.


fYpos += 50;                                                                                                                   
FacebookManager.GetInstance().strPostMsg = GUI.TextField(new Rect(0, fYpos, 300, 50), FacebookManager.GetInstance().strPostMsg);
                                                                                                                              
fYpos += 50;                                                                                                                   
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Post") == true)                                                                 
{                                                                                                                             
FacebookManager.GetInstance().PostToMeWall( FacebookManager.GetInstance().strPostMsg );                                     
}

 GUI 쪽 추가된 내용이구요. 텍스트 입력을 위해 텍스트필드를 추가하고 위에 추가했던 변수에 넣어줍니다. Post를 누르면 페이스북메니저를 통해 자바가 호출되겠지요.
 

 test facebook post by unity3d라고 입력했습니다.
 

 제 페이스북 담벼락에 게시된 내용입니다. curl로 담벼락에 게시할 때는 한글이 깨졌었는데 유니티에서는 잘 되네요.


2. 자신의 정보를 얻기

public void requestMe_U() {
runOnUiThread(new Runnable(){
public void run() {
Session session = Session.getActiveSession();
Request.executeMeRequestAsync(session, new Request.GraphUserCallback() {

@Override
public void onCompleted(GraphUser user, Response response) {
// TODO Auto-generated method stub
if (user != null) {
Log.d("UnityFacebookTest", user.getId());
Log.d("UnityFacebookTest", user.getName());

JSONObject jsonObj = new JSONObject();
try {
jsonObj.put(user.getId(), user.getName());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
            });
}
});
}

 자신의 정보를 요청해서 간단히 id와 이름을 출력하는 내용입니다. Request.executeMeRequestAsync를 안쓰고 위 처럼 Request와 Bundle에 직접 graph api 인자들을 넣어서 요청해도 가능합니다. 한가지 접근 api만 있는건 아닌거죠.

///< 페이스북 메니져 컴포넌트에 추가
public void RequestMe()         
{                               
curActivity.Call("requestMe_U");
}                               

///< GUI 컴포넌트에 추가
fYpos += 50;                                                         
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Me") == true)     
{                                                               
FacebookManager.GetInstance().RequestMe();           
}


3. 자신의 프로필 사진 이미지 출력

private Texture2D curDownTex = null;
private Texture2D texMe = null;


fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Me") == true)
{
//FacebookManager.GetInstance().RequestMe();
///*
StartCoroutine(MyPicDown("wwforever80"));
//*/
}

fYpos += 50;
if ( texMe != null )
{
GUI.DrawTexture(new Rect(0, fYpos, texMe.width, texMe.height), texMe);
}


private IEnumerator MyPicDown(string strId)
{
yield return StartCoroutine( DownPic(strId) );
texMe = curDownTex;
}


private IEnumerator DownPic(string strFacebookId)
{
string strPicUrl;
strPicUrl = System.String.Format("http://graph.facebook.com/{0}/picture", strFacebookId);
WWW www = new WWW(strPicUrl);
Debug.Log(strPicUrl);

yield return www;

if (www.error != null)
{
Debug.Log("Picture error");
}
else
{
curDownTex = www.texture;
//www.LoadImageIntoTexture(curDownTex);
Debug.Log(www.url);
}
}

 페이스북 프로필 이미지를 코루틴과 WWW로 다운받아 Texture2D로 저장하고 출력하는 부분입니다. 전부 GUI 컴포넌트쪽이구요. graph api중 picture인 http://graph.facebook.com/{0}/picture 부분에서 전 제 영문 ID를 바로 넘겨줬는데 위에서 알아낸 숫자 id를 넘겨줘도 됩니다.
 

 이제 빌드 후 실행해보면 위와 같이 페이스북 프로필 사진이 출력됩니다.

 다음에는 친구 목록을 얻어와서 친구들의 프로필 사진을 랜덤하게 출력하는 것을 정리해보겠습니다.

 

 

 

 

 

유니티3D 페이스북 SDK 안드로이드 연동 관련 자신의 담벼락 게시 및 자신의 프로필 이미지 출력까지 해봤습니다. 이번 포스팅은 페이스북 친구 목록을 얻어와서 친구의 프로필 사진을 유니티3D로 렌더링하는 것까지 정리해보겠습니다.


1. 친구 목록 가져오기

public void requestFriends_U() {
runOnUiThread(new Runnable(){
public void run() {
Session session = Session.getActiveSession();
            Request.executeMyFriendsRequestAsync(session, new Request.GraphUserListCallback() {

@Override
public void onCompleted(List<GraphUser> users,
Response response) {
// TODO Auto-generated method stub
if (users != null) {
JSONArray jsonArr = new JSONArray();

for (GraphUser user : users) {
Log.d("UnityFacebookTest", user.getName() + " " + user.getId());
try {
JSONObject jsonObj = new JSONObject();
jsonObj.put("FacebookId", user.getId());
jsonObj.put("Name", user.getName());
jsonArr.put(jsonObj);
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

UnityPlayer.UnitySendMessage("FacebookManager", "ResultFriends_J", jsonArr.toString());
}
}
            });
}
});
}

 먼저 자바쪽입니다. Request.executeMyFriendsRequestAsync를 통해 친구 목록을 요청합니다. Request.GraphUserListCallback의 onCoompleted에서 친구 목록을 JSONObject로 만들어 JSONArray에 쌓고있죠. 마지막에는 유니티3D에 json을 스트링형으로 넘겨줍니다.
 

 결과부터 보면 위와같이 로그로 잘 찍혔습니다. 이제 유니티3D부분을 보겠습니다.

using LitJson;

private Dictionary<string, string> dicFriends;

void Awake()
{
  ...
  this.dicFriends = new Dictionary<string, string>();
}


public void RequestFriends()
{
curActivity.Call("requestFriends_U");
}

public void ResultFriends_J(string jsonFriends)
{
JsonData jData = JsonMapper.ToObject(jsonFriends);
for (int i = 0 ; i < jData.Count ; i++)
{
string strFacebookId = jData[i]["FacebookId"].ToString();
string strFacebookName = jData[i]["Name"].ToString();
Debug.Log("Friend id " + strFacebookId + " Name " + strFacebookName);
this.dicFriends.Add(strFacebookId, strFacebookName);
}
Debug.Log("Friend Count = " + this.dicFriends.Count.ToString());
}

 FacebookManager 컴포넌트에 추가된 부분입니다. 친구 목록을 스트링으로 받아와서 JSON 객체로 만든 후 Dictionary에 추가하고 있습니다. C#에서 JSON을 사용하기 위해 저는  LitJson을 사용했습니다. 링크를 참고하세요.


class Friend                         
{                                 
public Texture2D texFriend = null;
public Rect rtTexPos;           
}                                 
                                   
List<Friend> listFriend = null;   

void OnGUI()
{
...
fYpos += 50;                                                             
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Get Friends\nList") == true)
{                                                                       
FacebookManager.GetInstance().RequestFriends();
}                                                                       
}

 TestGUI 컴포넌트 부분입니다.


2. 친구 프로필 사진 출력하기
 

 위 내용과 아래에 나올 GUI쪽 작업을 하면 위와 같이 생겼습니다. 이번에는 자바쪽은 없고 유니티3D쪽 C# 작업만 있습니다.

public Dictionary<string, string> GetFriends()
{
return this.dicFriends;
}

 쌓아둔 친구 목록을 통째로 가져오기 위해 FacebookManager 컴포넌트에 위와같은 함수를 추가합니다.


fYpos += 50;
if (GUI.Button (new Rect(0, fYpos, 100, 50), "Down Friends\nPic") == true)
{
StartCoroutine(DownFriendPic());
}

if (this.listFriend != null)
{
for ( int i = 0 ; i < this.listFriend.Count ; i++)
{
if (this.listFriend[i].texFriend != null)
GUI.DrawTexture(this.listFriend[i].rtTexPos, this.listFriend[i].texFriend);
}
}

 TestGUI 컴포넌트 OnGUI에 위와같이 친구의 사진을 다운로드할 버튼을 추가하고 친구 프로필 사진을 그려주는 GUI.DrawTexture를 추가합니다.


private IEnumerator DownFriendPic()                                                     
{                                                                                       
Dictionary<string, string> dicFriends;                                                 
dicFriends = new Dictionary<string, string>(FacebookManager.GetInstance().GetFriends());
if (dicFriends.Count > 0)                                                             
{                                                                                     
Debug.Log ("Friends num " + dicFriends.Count.ToString());                           
                                                                                     
this.listFriend = new List<Friend>();                                               
                                                                                       
foreach (KeyValuePair<string, string> pair in dicFriends)                           
{                                                                                   
Friend friend = new Friend();                                                     
                                                                                   
yield return StartCoroutine( DownPic(pair.Key) );                                 
                                                                                   
friend.rtTexPos = new Rect(                                                       
Random.Range(0, Screen.width)                                                   
, Random.Range(0, Screen.height)                                                 
, 50, 50);                                                                       
friend.texFriend = curDownTex;                                                     
this.listFriend.Add(friend);                                                       
}                                                                                   
}                                                                                     


 코루틴을 사용해서 친구의 프로필 사진을 WWW로 다운받아 Texture2D에 저장합니다. 위치는 랜덤하게 잡아줬습니다.
 

 버튼을 누르면 친구 사진이 다운로드가 됩니다. 코루틴을 사용하기 때문에 비동기로 하나씩 렌더링이 되죠.
 

 친구 프로필 사진이 모두 그려진 상태입니다.

 간단히? 유니티3D에 페이스북 안드로이드 연동 포스팅을 해봤습니다. 여기서 더 해나갈지는 두고봐야겠네요.

 

 

 

 

 

출처 : http://westwoodforever.blogspot.kr/

Posted by 프리랜서 디자이너
TA/Unity2013. 7. 23. 17:37

http://xamarin.com/

 

 

 

자마린 스튜디오
자마린 스튜디오(Xamarin Studio)는 멀티 플랫폼 네이티브 모바일 앱을 설계, 개발, 디버깅, 배치할 수 있는 간소화된 IDE다. 음악 스트리밍 업체 알디오(Rdio)는 자마린 스튜디오와 자마린의 안드로이드, iOS 개발 기술을 이용해 개발 작업을 최소화할 수 있었다.
알디오의 수석 안드로이드 개발자 브렛 던카비니는 “우리는 안드로이드와 iOS 두 플랫폼 모두를 위한 대규모 팀을 구성하지 않고도 앱의 기능을 동등하게 만들 수 있는 방법을 찾고 있었다"며 "현재는 안드로이드와 iOS 사이에 대략 60% 정도 코드를 공유하고 있다"고 말했다 "이어 "앱 개발은 주로 C# 언어를 이용하고 있다"며 "자마린 스튜디오는 훌륭한 코드 완성, 디버깅, 개발 능력을 제공하지만 여전히 성숙도가 부족한 면이 있다"고 지적했다.

Posted by 프리랜서 디자이너
TA/Unity2013. 6. 21. 10:03

iTween Path collider충돌시 멈추기

 

using UnityEngine;
using System.Collections;

public class test : MonoBehaviour {


 
 void Start () {
 iTween.MoveTo(gameObject, iTween.Hash("path", iTweenPath.GetPath("New Path 3"), "time",5,"easetype",iTween.EaseType.linear));
 }
 
 void stop(){
  iTween.Stop(gameObject);
 }
 
 void OnTriggerEnter(Collider col)
 {
  stop();
 }
}

Posted by 프리랜서 디자이너
TA/Unity2013. 6. 21. 07:41

ITween Example Tutorial

 

http://hatoru.tistory.com/157

 

< 유니티 에셋 1 : ITween Example Tutorial > 

*공식 ITween Example : http://itween.pixelplacement.com/examples.php

Animating 2D(GUITextures)

-GUITextures를 이용한 2D 애니메이션를 ITween으로 구현한다.



1. 패키지를 Import 한다.
[ Assets - Import Package - Custom Package... ]



2. GUITexture의 구성

 -PresentationScreen : 빈 오브젝트 (스크립트를 여기에 Add한다)
   -iTweenLogo
   -PresentsText
   -whiteDiagonalGradient : ( 자식 오브젝트는 모두 GUITexture이다)

* PresentationScreen 활성화

* TitleScreen 비활성화

 

3. GUITexture 만들기
Create Other - GUI Texture를 이용해서 만든다

4. GUITexture 좌표
 
 각 GUITexture의 Inspector의 Pixel Insert 좌표를 화면에 보여질 위치에 설정한다. 
  - 화면 밖에서 화면 안으로 들어 오는 효과 일 경우 이 좌표는 목적지가 된다. (IN : MoveFrom()함수 사용)
  - 화면 안에서 확면 밖으로 나가는 경우 이 좌표는 시작점이 된다.  (OUT : MoveTo()함수 사용)

5. iTween의 함수 사용 법

  iTween.MoveFrom(gameObject,iTween.Hash("x",-0.4,"time",0.6,"delay",1.2));
     --
x축 -0.4에서 부터 게임오브젝트에 설정되 좌표까지
      --속도(time)는 0.6
     --이동후 1.2의 시간 만큼 애니메이션 시간을 흘려보낸다(delay)

< iTween의 해쉬 String >

Property Name Type Purpose
name string an individual name useful for stopping iTweens by name
audiosource AudioSource for which AudioSource to use
volume float or double for the target level of volume
pitch float or double for the target pitch
time float or double

for the time in seconds the animation will take to complete
애니메이션이 완료되는 시간이며 속도를 설정한다.

delay float or double for the time in seconds the animation will wait before beginning
애니메이션 시작 전 대기 시간을 설정 한다.
easetype EaseType or string for the shape of the easing curve applied to the animation
애니메이션에 적용할  완곡 곡선 설정
looptype LoopType or string for the type of loop to apply once the animation has completed
onstart string for the name of a function to launch at the beginning of the animation
onstarttarget GameObject for a reference to the GameObject that holds the "onstart" method
onstartparams Object for arguments to be sent to the "onstart" method
onupdate string for the name of a function to launch on every step of the animation
onupdatetarget GameObject for a reference to the GameObject that holds the "onupdate" method
onupdateparams Object for arguments to be sent to the "onupdate" method
oncomplete string

for the name of a function to launch at the end of the animation
애니메이션이 끝났을때 지정된 함수를 수행한다.

oncompletetarget GameObject

for a reference to the GameObject that holds the "oncomplete" method
"oncomplete"를 hold하고 있는 게임오브젝트 참조

oncompleteparams Object for arguments to be sent to the "oncomplete" method
ignoretimescale boolean setting this to true will allow the animation to continue independent of the current time which is helpful for animating menus after a game has been paused by setting Time.timeScale=0

예)
 void SwitchToTitleScreen()
{
    gameObject.SetActiveRecursively(false);  //현재 오브젝트를 비활성화 시킨다.
    titleScreen.SetActiveRecursively(true);     //다음 오브젝트를 활성화 시킨다.
}
==> 애니메이션이 끝나고 Swtich() 함수를 부르기 위한 hash String을 사용한다. 
        "oncomplete"

iTween.FadeTo(whiteDiagonalGradient,iTween.Hash("alpha",0,"time",.6,"delay",2.8,"easetype","easeincubic"
                    ,"oncomplete","SwitchToTitleScreen","oncompletetarget",gameObject));

< iTween 함수 >

구분

함수 

설명 

 Scale

scaleTo()
scaleFrom() 

 

Punches 

 punchPosition()
punchRotation()

 

Shake 

shake() 

 

Stab 

 stab()

 

Audio 

 audioTo()

 

Rotate 

roateTo()
rotateFrom()
rotateBy() 

 

Fade 

fadeTo()
fadeFrom() 

 

color 

colorTo() 
colorFrom()

 

Movement 

moveTo()
moveFrom()
moveToBezier() 

 


< iTween easing type >
링크 : http://www.robertpenner.com/easing/



6. coroutin을 이용한 활성화/비활성화
IEnumerator SwitchToPresentationScreen()
{
   yield return new WaitForSeconds(2);                   //2초간 대기한다.
    gameObject.SetActiveRecursively(false);            //현재 오브젝트 비활성화
    presentationScreen.SetActiveRecursively(true);  //활성화

}

void Update()
{
    if(Input.GetMouseButtonDown(0))  //coroutine 이 실행될 조건
    {
        StartCoroutine(SwitchToPresentationScreen());   
    }
}

'TA > Unity' 카테고리의 다른 글

SDK....빌드셋팅 한방 Xamarin...  (0) 2013.07.23
iTween Path collider 충돌시 멈추기  (0) 2013.06.21
유니티 라이트 프로브 셰이더 예제  (0) 2013.06.20
TD CameraControl C#  (0) 2013.05.09
유니티 C# 공부 모음  (0) 2013.05.07
Posted by 프리랜서 디자이너
TA/Unity2013. 6. 20. 10:59

유니티 라이트 프로브 셰이더 예제

 

 

 

 

플레그먼트

 

Shader "Probes" {
Properties {
_MainTex ("Base (RGB) Gloss (A)", 2D) = "white" {}
_SHLightingScale("LightProbe influence scale",float) = 1
}

SubShader {
Tags { "RenderType"="Opaque" "LightMode"="ForwardBase"}
LOD 100

CGINCLUDE
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#include "UnityCG.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;

float _SHLightingScale;

struct v2f {
float4 pos : SV_POSITION;
float2 uv : TEXCOORD0;
fixed3 spec : TEXCOORD1;
fixed3 SHLighting: TEXCOORD2;
};


v2f vert (appdata_full v)
{
v2f o;
o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
o.uv = v.texcoord;
float3 worldNormal = mul((float3x3)_Object2World, v.normal);
float3 shl = ShadeSH9(float4(worldNormal,1));
o.SHLighting = shl * _SHLightingScale;

return o;
}
ENDCG

Pass {
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma fragmentoption ARB_precision_hint_fastest
fixed4 frag (v2f i) : COLOR
{
fixed4 c = tex2D (_MainTex, i.uv);

c.rgb *= i.SHLighting;

return c;
}
ENDCG 
}
}
}

 

 

 

서피스

 

Shader "Custom/ModifyLightProbes" {

 

Properties {  _Color ("Main Color", Color) = (1,1,1,1)      

         _MainTex ("Base (RGB)", 2D) = "white" {} 

  _Amount ("SH scale", Float) = 1   

}   

 

SubShader {  

      Tags { "RenderType"="Opaque" }       

LOD 200               

CGPROGRAM       

#pragma surface surf Lambert noambient vertex:vert       

#pragma debug        

 

sampler2D _MainTex;       

fixed4 _Color;       

float _Amount;        

 

struct Input {  

float2 uv_MainTex;           

float3 shLight;       

 };               

 

 

void vert (inout appdata_full v, out Input o) {

            // evaluate SH light           

float3 worldN = mul ((float3x3)_Object2World, SCALED_NORMAL);           

o.shLight = ShadeSH9 (float4 (worldN, 1.0));       

}        

 

 

 

void surf (Input IN, inout SurfaceOutput o) {           

half4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color;           

     o.Albedo = c.rgb;           

o.Alpha = c.a;                       

 

// modify the SH lighting anyway you want,           

// here's just simple scaling           

float3 shLight = _Amount * IN.shLight;       

                

// emission is just added to the final color,           

     // so SH light needs to be multiplied by albedo           

o.Emission = o.Albedo * shLight; 

     

}       

ENDCG   

 }   

FallBack "Diffuse"

}

 

 

 

'TA > Unity' 카테고리의 다른 글

iTween Path collider 충돌시 멈추기  (0) 2013.06.21
ITween Example Tutorial  (0) 2013.06.21
TD CameraControl C#  (0) 2013.05.09
유니티 C# 공부 모음  (0) 2013.05.07
Texture Matrix in Fixed Function  (0) 2012.07.18
Posted by 프리랜서 디자이너
TA/Unity2013. 5. 9. 07:53

TD 예제 스크립트 카메라 컨트롤러

 

using UnityEngine;
using System.Collections;

 

#pragma warning disable 0168 // variable declared but not used.
#pragma warning disable 0219 // variable assigned but not used.
#pragma warning disable 0414 // private field assigned but not used.

 

public class CameraControl : MonoBehaviour {

 //public enum _Platform{Hybird, Mouse&Keyboard, Touch} 키보드와 터치 모두 가능....
 //public _Platform platform;

 

 public float panSpeed=5;
 public float zoomSpeed=5;
 
 private float initialMousePosX;
 private float initialMousePosY;
 
 private float initialRotX;
 private float initialRotY;
 
 
 public float minPosX=-10;
 public float maxPosX=10;
 
 public float minPosZ=-10;
 public float maxPosZ=10;
 
 public float minRadius=8;
 public float maxRadius=30;
 
 public float minRotateAngle=10;
 public float maxRotateAngle=89;

 //calculated deltaTime based on timeScale so camera movement speed always remain constant
 private float deltaT;
 
 private Transform cam;
 private Transform thisT;

 void Awake(){
  thisT=transform;
  
  cam=Camera.main.transform;
 }
 
 // Use this for initialization
 void Start () {
  minRotateAngle=Mathf.Max(10, minRotateAngle);
  maxRotateAngle=Mathf.Min(89, maxRotateAngle);
  
  minRadius=Mathf.Max(1, minRadius);
 }
 
 // Update is called once per frame
 void Update () {
  
  if(Time.timeScale==1) deltaT=Time.deltaTime;
  else deltaT=Time.deltaTime/Time.timeScale;
  
  
  #if UNITY_EDITOR || (!UNITY_IPHONE && !UNITY_ANDROID)
  
  //mouse and keyboard
  if(Input.GetMouseButtonDown(1)){
   initialMousePosX=Input.mousePosition.x;
   initialMousePosY=Input.mousePosition.y;
   initialRotX=thisT.eulerAngles.y;
   initialRotY=thisT.eulerAngles.x;
  }

  if(Input.GetMouseButton(1)){
   float deltaX=Input.mousePosition.x-initialMousePosX;
   float deltaRotX=(.1f*(initialRotX/Screen.width));
   float rotX=deltaX+deltaRotX;
   
   float deltaY=initialMousePosY-Input.mousePosition.y;
   float deltaRotY=-(.1f*(initialRotY/Screen.height));
   float rotY=deltaY+deltaRotY;
   float y=rotY+initialRotY;
   
   //limit the rotation
   if(y>maxRotateAngle){
    initialRotY-=(rotY+initialRotY)-maxRotateAngle;
    y=maxRotateAngle;
   }
   else if(y<minRotateAngle){
    initialRotY+=minRotateAngle-(rotY+initialRotY);
    y=minRotateAngle;
   }
   
   thisT.rotation=Quaternion.Euler(y, rotX+initialRotX, 0);
  }
  
  
  Quaternion direction=Quaternion.Euler(0, thisT.eulerAngles.y, 0);
  
  if(Input.GetButton("Horizontal")) {
   Vector3 dir=transform.InverseTransformDirection(direction*Vector3.right);
   thisT.Translate (dir * panSpeed * deltaT * Input.GetAxisRaw("Horizontal"));
  }

  if(Input.GetButton("Vertical")) {
   Vector3 dir=transform.InverseTransformDirection(direction*Vector3.forward);
   thisT.Translate (dir * panSpeed * deltaT * Input.GetAxisRaw("Vertical"));
  }
  
  //cam.Translate(Vector3.forward*zoomSpeed*Input.GetAxis("Mouse ScrollWheel"));
  
  if(Input.GetAxis("Mouse ScrollWheel")<0){
   if(Vector3.Distance(cam.position, thisT.position)<maxRadius){
    cam.Translate(Vector3.forward*zoomSpeed*Input.GetAxis("Mouse ScrollWheel"));
   }
  }
  else if(Input.GetAxis("Mouse ScrollWheel")>0){
   if(Vector3.Distance(cam.position, thisT.position)>minRadius){
    cam.Translate(Vector3.forward*zoomSpeed*Input.GetAxis("Mouse ScrollWheel"));
   }
  }
  
  //thisT.Translate(cam.forward*zoomSpeed*Input.GetAxis("Mouse ScrollWheel"), Space.World);
  
  #endif
  
  float x=Mathf.Clamp(thisT.position.x, minPosX, maxPosX);
  float z=Mathf.Clamp(thisT.position.z, minPosZ, maxPosZ);
  //float y=Mathf.Clamp(thisT.position.y, verticalLimitBottom, verticalLimitTop);
  
  thisT.position=new Vector3(x, thisT.position.y, z);
  
 }
 
 
 public bool showGizmo=true;
 void OnDrawGizmos(){
  if(showGizmo){
   Vector3 p1=new Vector3(minPosX, transform.position.y, maxPosZ);
   Vector3 p2=new Vector3(maxPosX, transform.position.y, maxPosZ);
   Vector3 p3=new Vector3(maxPosX, transform.position.y, minPosZ);
   Vector3 p4=new Vector3(minPosX, transform.position.y, minPosZ);
   
   Gizmos.color=Color.green;
   Gizmos.DrawLine(p1, p2);
   Gizmos.DrawLine(p2, p3);
   Gizmos.DrawLine(p3, p4);
   Gizmos.DrawLine(p4, p1);
  }
 }
 
}

'TA > Unity' 카테고리의 다른 글

ITween Example Tutorial  (0) 2013.06.21
유니티 라이트 프로브 셰이더 예제  (0) 2013.06.20
유니티 C# 공부 모음  (0) 2013.05.07
Texture Matrix in Fixed Function  (0) 2012.07.18
HLSL 함수  (0) 2012.07.10
Posted by 프리랜서 디자이너
TA/Unity2013. 5. 7. 08:42

유니티 C# 공부 모음 01

 

 

오브젝트 배열 잡기

.

.Public class ex: MonoBehaviour {

//클레스

 

private int currentWaypoint = 0;

//배열갯수 인스펙터에서 조절 가능하게 전역변수로....

 

GameObject AAA;

GameObject BBB;

//변수 설정

 

void Start () {

 

       AAA= GameObject.Find("AAA_01");

BBB= GameObject.Find("AAA_01");

//게임오브젝트 담기

 

waypoints[0] = AAA.transform;

waypoints[1] = BBB.transform;

//배열지정하기

}//스타트

.

.

void Update () {

activeWaypoint = waypoints[currentWaypoint];

//activeWaypoint 변수에 배열 넘겨 저장 시키기.

}//업데이트

.

.

}//클레스

 

 

 

 

=====================================================================================================================

 

OnTriggerEnter 예제

void OnTriggerEnter(Collider col)
 {
  
      Debug.Log("collider Trigger!");
      if(col.gameObject.tag == "waypoint")
      {
           currentWaypoint++;
           Debug.Log("current no = " +currentWaypoint);
      }
  
      if(state == 0)
      {
           if(currentWaypoint != 9){
           wark();
           }else{
                Destroy(this.gameObject);
           }
      }
 }

 

// OnTriggerEnter(Collider col) 트리거 충돌시 자동 호출된다. 단 유닛에 리지드바디가 추가되어있어야함.

 

 

=====================================================================================================================

 

 

 

오브젝트 카메라 바라보게 만들기.

using UnityEngine;
using System.Collections;

 

public class LookAtCamera : MonoBehaviour {
 
 public Camera cameraToLookAt;

//전역변수로 카메라 타입의 변수 생성

 


 void Start () {
  cameraToLookAt = Camera.main;

변수에 카메라담기 초기화...작업
 }
 



 void Update () {
  Vector3 v = cameraToLookAt.transform.position - transform.position;

//카메라 위치 구하기


  v.x = v.z = 0.0f;

//x와z축 0.0f로 만들기


  transform.LookAt(cameraToLookAt.transform.position - v);

//카메라를 y축을 중심으로 바라보게 만들기.
 }
}

 

 

=====================================================================================================================

 

 

인스턴스 만들고 오브젝트 발사하기

 

public Rigidbody FireBall;

public float FireBallSpeed = 1.0f;

.

.

.

Rigidbody playerAttak = (Rigidbody)Instantiate(FireBall,transform.position,transform.rotation);
playerAttak.velocity = transform.TransformDirection(new Vector3(0,0,FireBallSpeed));

 

=====================================================================================================================

 

오브젝트간 거리 구하기

 

float Distance = Vector3.Distance(obj1.transform.position, obj2.transform.position);

Distance 함수를 사용해 거리를 구한다.

 

 

=====================================================================================================================

 

 

A오브젝트가 B오브젝트를 바라보게 만들기

 

transform.rotation = Quaternion.Slerp(Creep.transform.rotation, Quaternion.LookRotation(Target.transform.position - Creep.transform.position), 1);

 

Quaternion함수를 (축) 같은 축으로 만들기

Slerp 함수는 보간기능

LookRotation() 은 특정 오브젝트를 바라보개 만든다,

 

 

=====================================================================================================================

 

오브젝트에 시간을 곱해 좌표이동시키기

transform.Translate(Vector3.forward * Time.smoothDeltaTime * MoveSpeed);

 

// Translate(Vector3)

 

=====================================================================================================================

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

'TA > Unity' 카테고리의 다른 글

유니티 라이트 프로브 셰이더 예제  (0) 2013.06.20
TD CameraControl C#  (0) 2013.05.09
Texture Matrix in Fixed Function  (0) 2012.07.18
HLSL 함수  (0) 2012.07.10
Blending modes..참고 자료  (0) 2012.06.08
Posted by 프리랜서 디자이너

Custom Lighting models in Surface Shaders

Surface Shaders를 쓸 때, 사용자는 표면(albedo color, normal, ...)의 속성을 설명하고 있고 조명 상호 작용이 조명 모델(Lighting Model).

내장된 조명 모델이 Lambert (diffuse 조명)이고 BlinnPhong (반사적인 조명) 입니다.

 

때때로 사용자는 사용자 정의 조명 모델을 사용하기를 원할지도 모르고 표면 쉐이더에서 저것을 하는 것이 가능합니다.

조명 모델이 어떤 규칙을 매치하는Cg/HLSL 함수 두 개보다 더 많지 않습니다. 내장된 LambertBlinnPhong 모델은 Unity 안의 Lighting.cginc 파일에서 정의됩니다(Windows에서 {unity install path}/Data/CGIncludes/Lighting.cginc, Mac에서 /Applications/Unity/Unity.app/Contents/CGIncludes/Lighting.cginc).

Lighting Model declaration

조명 모델은 Lighting으로 시작하는 이름을 가지는 일반 함수 2개 입니다. 그들은 사용자의 쉐이더 파일 또는included 파일 중 하나에서 어디서나 선언될 수 있습니다. 함수는 이것과 같습니다:

  1. half4 LightingName (SurfaceOutput s, half3 lightDir, half atten);이것은 뷰 디렉션에 의존하지 않는 포워드 렌더링 경로에서 사용됩니다 (예. diffuse).
  2. half4 LightingName (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten);이것은 뷰 디렉션에 의존하는 조명 모델을 위한 포워드 렌더링 경로에서 사용됩니다.
  3. half4 LightingName_PrePass (SurfaceOutput s, half4 light);이것은 deferred 조명 경로에서 사용됩니다.

사용자가 모든 함수를 선언할 필요가 없다는 것을 참고하세요.

조명 모델은 뷰 디렉션을 사용하거나 또는 하지 않는다는 것입니다.

 

 

 

유사하게 조명 모델이 deferred 조명에서 작동하지 않는다면 사용자는 _PrePass 함수를 선언하지 않고 그것을 사용하는 모든 쉐이더가 포워드 렌더링만으로 컴파일할 것입니다.

 

 

 

 

디렉셔널 라이트맵 디코딩은 어떤 상황들에서는 조명이 포워드와 지연 조명에서처럼 비슷한 방식으로 사용자화(customizing) 될 필요가 있습니다.

 

당신의 라이트 모델이 보는 방향에 의존적인지 아닌지에 따라 아래의 함수 중 하나를 사용하세요.

두개의 함수 다 포워드라이팅과 지연라이팅 렌더링 경로를 자동으로 처리합니다.

  1. half4 LightingName_DirLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal);이것은 보는 방향 의존적이지 않은 라이트 모델들에 사용됩니다 (e.g. diffuse).

이것은 종속 방향을 볼 수 없습니다 빛이 모델에 사용됩니다(e.g. diffuse).

  1. half4 LightingName_DirLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, half3 viewDir, bool surfFuncWritesNormal, out half3 specColor);이것은 보는 방향 의존적인 라이트 모델들에 사용됩니다.

 

 

 

 

 

 

'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

SurfaceShaderLighting  (0) 2012.07.26
SurfaceShaders  (0) 2012.07.26
한방에 모아보는 레퍼런스  (1) 2012.07.20
Pass  (0) 2012.07.19
Category  (0) 2012.07.18
Posted by 프리랜서 디자이너

Custom Lighting models in Surface Shaders

Surface Shaders를 쓸 때, 사용자는 표면(albedo color, normal, ...)의 속성을 설명하고 있고 조명 상호 작용이 조명 모델(Lighting Model). 내장된 조명 모델이 Lambert (diffuse 조명)이고 BlinnPhong (반사적인 조명) 입니다.

때때로 사용자는 사용자 정의 조명 모델을 사용하기를 원할지도 모르고 표면 쉐이더에서 저것을 하는 것이 가능합니다. 조명 모델이 어떤 규칙을 매치하는Cg/HLSL 함수 두 개보다 더 많지 않습니다. 내장된 LambertBlinnPhong 모델은 Unity 안의 Lighting.cginc 파일에서 정의됩니다(Windows에서 {unity install path}/Data/CGIncludes/Lighting.cginc, Mac에서 /Applications/Unity/Unity.app/Contents/CGIncludes/Lighting.cginc).

Lighting Model declaration

조명 모델은 Lighting으로 시작하는 이름을 가지는 일반 함수 2개 입니다. 그들은 사용자의 쉐이더 파일 또는included 파일 중 하나에서 어디서나 선언될 수 있습니다. 함수는 이것과 같습니다:

  1. half4 LightingName (SurfaceOutput s, half3 lightDir, half atten);이것은 뷰 디렉션에 의존하지 않는 포워드 렌더링 경로에서 사용됩니다 (예. diffuse).
  2. half4 LightingName (SurfaceOutput s, half3 lightDir, half3 viewDir, half atten);이것은 뷰 디렉션에 의존하는 조명 모델을 위한 포워드 렌더링 경로에서 사용됩니다.
  3. half4 LightingName_PrePass (SurfaceOutput s, half4 light);이것은 deferred 조명 경로에서 사용됩니다.

사용자가 모든 함수를 선언할 필요가 없다는 것을 참고하세요. 조명 모델은 뷰 디렉션을 사용하거나 또는 하지 않는다는 것입니다. 유사하게 조명 모델이 deferred 조명에서 작동하지 않는다면 사용자는 _PrePass 함수를 선언하지 않고 그것을 사용하는 모든 쉐이더가 포워드 렌더링만으로 컴파일할 것입니다.

디렉셔널 라이트맵 디코딩은 어떤 상황들에서는 조명이 포워드와 지연 조명에서처럼 비슷한 방식으로 사용자화(customizing) 될 필요가 있습니다. 당신의 라이트 모델이 보는 방향에 의존적인지 아닌지에 따라 아래의 함수 중 하나를 사용하세요. 두개의 함수 다 포워드라이팅과 지연라이팅 렌더링 경로를 자동으로 처리합니다.

  1. half4 LightingName_DirLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, bool surfFuncWritesNormal);이것은 보는 방향 의존적이지 않은 라이트 모델들에 사용됩니다 (e.g. diffuse).

This is used for light models that are not view direction dependent (e.g. diffuse).

  1. half4 LightingName_DirLightmap (SurfaceOutput s, fixed4 color, fixed4 scale, half3 viewDir, bool surfFuncWritesNormal, out half3 specColor);이것은 보는 방향 의존적인 라이트 모델들에 사용됩니다.

예제 Examples

Surface Shader Lighting Examples

 

'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

Custom Lighting models in Surface Shaders  (0) 2012.08.24
SurfaceShaders  (0) 2012.07.26
한방에 모아보는 레퍼런스  (1) 2012.07.20
Pass  (0) 2012.07.19
Category  (0) 2012.07.18
Posted by 프리랜서 디자이너

Writing Surface Shaders

조명과 상호작용하는 쉐이더를 쓰는 것은 복잡합니다. 다른 조명 타입과 그림자 옵션, 렌더링 경로 (포워드 그리고 지연 렌더링)이 있고 쉐이더는 모든 복잡성을 다뤄야만 합니다.

Unity에서 Surface Shaders는 낮은 레벨의 vertex/pixel shader programs을 사용하는 것 보다 조명 쉐이더를 쓰는 것을 더욱 쉽게 만드는 코드 생성 방법입니다. 표면 쉐이더에 연관된 사용자 정의 언어, 마술 또는 닌자가 없다는 것을 참고하세요; 그것은 단지 손으로 쓰여져야하는 모든 반복적인 코드를 생성합니다. 사용자는 여전히Cg / HLSL로 쉐이더 코드를 씁니다.

예를 위해서 Surface Shader ExamplesSurface Shader Custom Lighting Examples를 살펴보시기 바랍니다.

How it works

사용자는 사용자가 입력값으로 필요로 하는 어떠한UVs 또는 데이터를 취하는 "surface function"을 정의하고 결과 구조 SurfaceOutput를 채웁니다. SurfaceOutput은 기본적으로 표면의 속성을 설명합니다 (그것은albedo 색상, normal, 발산, 반사 등). 사용자는Cg / HLSL로 이 코드를 씁니다.

표면 쉐이더 컴파일러는 그 때 어떤 입력값이 필요되어 지는지, 무슨 결과가 채워지는 지 등을 알아내고 포워드 그리고 지연 렌더링을 처리하기 위해 패스들을 렌더링할 뿐만 아니라 실제 vertex&pixel shaders를 생성합니다.

표면 쉐이더의 기본적인 결과 구조는 이것입니다:

struct SurfaceOutput {
    half3 Albedo;
    half3 Normal;
    half3 Emission;
    half Specular;
    half Gloss;
    half Alpha;
};

Samples

Surface Shader ExamplesSurface Shader Custom Lighting Examples 페이지를 살펴보시기 바랍니다.

Surface Shader compile directives

표면 쉐이더는 다른 쉐이더들 처럼 CGPROGRAM..ENDCG 블록 사이에 놓여집니다. 차이는 이것입니다:

  • 그것은 SubShader 안이 아닌 Pass 블록안에 놓여져야만 합니다. 표면 쉐이더는 다수의 패스들로 스스로 컴파일 할 것입니다.

그것은 그것이 표면 쉐이더라는 것을 알리기 위해 #pragma surface 지시어를 사용합니다:

    #pragma surface surfaceFunction lightModel [optionalparams]

Required parameters:

  • surfaceFunction - 어떤Cg 함수가 표면 쉐이더 코드를 가지는지 입니다. 함수는 void surf (Input IN, inout SurfaceOutput o)의 형태를 가져야 합니다. 거기서 입력값은 사용자가 정의한 구조입니다. 입력값은 어떠한 텍스쳐 좌표라도 포함해야 하고 표면 함수에 의해 필요되는 여분의 자동 변수들도 포함해야 합니다
  • lightModel - 사용하는 조명 모델. 내장된 것들은 Lambert (diffuse) 와 BlinnPhong (specular) 입니다. 사용자 자신의 것을 쓰는 방법을 위해서는 Custom Lighting Models 페이지를 참고하시기 바랍니다.

Optional parameters:

  • alpha - 알파 블렌딩 모드. 반투명 쉐이더를 위해서 이것을 사용합니다.
  • alphatest:VariableName - 알파 테스팅 모드. 투명하고 컷아웃 쉐이더를 위해서 이것을 사용합니다. 컷오프 값은VariableName과 함께 소수점 변수안에 있습니다.
  • vertex:VertexFunction - 사용자 정의 꼭지점 변형 함수. 예를 위해서Tree Bark를 살펴보세요.
  • exclude_path:prepass or exclude_path:forward - 주어진 렌더링 경로를 위해서 패스를 생성하지 마십시오.
  • dualforward - dual lightmaps 렌더링 경로에서 [[RenderTech-ForwardRendering | forward을 사용합니다.
  • fullforwardshadows - Forward 렌더링 경로에서 모든 그림자 타입을 지원합니다.
  • decal:add - 첨가하는 데칼 쉐이더 (예. terrain AddPass).
  • decal:blend - 반투명 데칼 쉐이더
  • softvegetation - 오직Soft Vegetation이 활성화될 때 표면 쉐이더가 그려지도록 만듭니다.
  • noambient - 주변의 조명이나 또는 주변의 고조파 조명도 적용하지 않습니다.
  • novertexlights - 포워드 렌더링에서 주변의 고조파 조명이나 또는 정점 조명도 적용하지 않습니다.
  • nolightmap - Lightmap 이 쉐이더에서 지원을 비활성화 합니다 (쉐이더를 더 작게 만듭니다).* noforwardadd - Forward 렌더링 첨가적인 패스를 비활성화 합니다. 이것은 vertex/SH당 계산되는 모든 다른 조명과 함께 쉐이더가 하나의 완전한 방향성있는 조명을 지원하도록 만듭니다. 쉐이도를 역시 더 작게 만듭니다.
  • approxview - 그것을 필요로하는 쉐이더를 위해서 픽셀당 대신에 정점당 일반화된 뷰 디렉션을 계산합니다. 이것은 더 빠르나 뷰 디렉션은 카메라가 표면에 가까울 때 완전히 옳은 것은 아닙니다.
  • halfasview - 뷰 디렉션 대신에 조명 함수로 절반 방향 벡터를 패스합니다. 절반 방향은 정점당 계산될 것이고 일반화될 것입니다. 이것은 더 빠르나 완전히 옳지는 않습니다.

또한 사용자는CGPROGRAM 블록 안에서 #pragma debug쓸 수 있고 그 후에 표면 컴파일러는 생성된 코드의 많은 코멘트들을 나눌 것입니다. 사용자는 쉐이더 인스펙터에서Open Compiled Shader을 사용하는 것을 볼 수 있습니다.

Surface Shader input structure

입력 구조 Input은 일반적으로 쉐이더에 의해 필요되어지는 어떠한 텍스쳐 좌표라도 가집니다. 텍스쳐 좌표는 텍스쳐 이름 다음에 "uv"라고 이름지어져야만 합니다.

 

입력 구조에 끼워 넣을 수 있는 추가적인 값들:

  • float3 viewDir - 뷰 디렉션을 포함할 것이고Parallax 효과를 위해서는rim 조명등이 포함될 것입니다.
  • float4 with COLOR semantic - 보간되는 정점당 색상을 포함할 것입니다.
  • float4 screenPos - w 반사 효과를 위해서 스크린 공간 위치를 포함할 것입니다. 예를 들어Dark Unity에서 WetStreet 쉐이더에 의해 사용됩니다.
  • float3 worldPos - 세계 공간 위치를 포함할 것입니다.
  • float3 worldRefl - 표면 쉐이더가o.Normal로 쓰여지지 않는다면 세계 반사 벡터를 포함할 것입니다. 예를 들어Reflect-Diffuse를 살펴보시기 바랍니다.
  • float3 worldNormal - 표면 쉐이더가o.Normal로 쓰여지지 않는다면 세계 normal 벡터를 포함할 것입니다.
  • float3 worldRefl; INTERNAL_DATA - 표면 쉐이더가o.Normal로 쓰여진다면 세계 반사 벡터를 포함할 것입니다. 픽셀당 normal map에 기반한 반사 벡터를 얻기 위해서 WorldReflectionVector (IN, o.Normal)을 사용하시기 바랍니다. 예를 위해서Reflect-Bumped를 참고하시기 바랍니다.
  • float3 worldNormal; INTERNAL_DATA - 표면 쉐이더가o.Normal로 쓰여진다면 세계 normal 벡터를 포함할 것입니다. 픽셀당 normal map에 기반한 반사 벡터를 얻기 위해서 WorldNormalVector (IN, o.Normal)을 사용하시기 바랍니다(IN, o.Normal)..

Further Documentation

'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

Custom Lighting models in Surface Shaders  (0) 2012.08.24
SurfaceShaderLighting  (0) 2012.07.26
한방에 모아보는 레퍼런스  (1) 2012.07.20
Pass  (0) 2012.07.19
Category  (0) 2012.07.18
Posted by 프리랜서 디자이너

한방에 모아보는 Unity Shader 레퍼런스

 

Properties

 

Properties {
    // properties for water shader
    _WaveScale ("Wave scale", Range (0.02,0.15)) = 0.07 // sliders
    _ReflDistort ("Reflection distort", Range (0,1.5)) = 0.5
    _RefrDistort ("Refraction distort", Range (0,1.5)) = 0.4
    _RefrColor ("Refraction color", Color)  = (.34, .85, .92, 1) // color
    _ReflectionTex ("Environment Reflection", 2D) = "" {} // textures
    _RefractionTex ("Environment Refraction", 2D) = "" {}
    _Fresnel ("Fresnel (A) ", 2D) = "" {}
    _BumpMap ("Bumpmap (RGB) ", 2D) = "" {}
}

 

Syntax

Properties { Property [Property ...] }
속성 블록을 정의합니다. 중괄호안에 다수의 속성은 다음과 같이 정의됩니다.
name ("display name", Range (min, max)) = number
인스펙터에서 minmax 사이의 슬라이더로 나타나는 소수점 속성을 정의합니다.
name ("display name", Color) = (number,number,number,number)
색상 속성을 정의합니다.
name ("display name", 2D) = "name" { options }
2D 텍스쳐 속성을 정의합니다.
name ("display name", Rect) = "name" { options }
직사각형 (2의 지수가 아닌) 텍스쳐 속성을 정의합니다.
name ("display name", Cube) = "name" { options }
Cubemap 텍스쳐 속성을 정의합니다.
name ("display name", Float) = number
소수점 속성을 정의합니다.
name ("display name", Vector) = (number,number,number,number)
네 개의 컴포넌트 벡터 속성을 정의합니다.

 

 

 

Texture property options

텍스쳐 속성의 괄호안의 옵션은 선택적입니다. 가능한 옵션은 다음과 같습니다:

TexGen texgenmode
이 텍스쳐를 위한 자동적인 텍스쳐 좌표 생성 모드. ObjectLinear, EyeLinear, SphereMap, CubeReflect, CubeNormal 중 하나일 수 있습니다; 이러한 것들은 직접적으로OpenGL texgen 모드와 관련됩니다. 사용자 정의 꼭지점 프로그램이 사용되면 TexGen이 무시되는 것을 참고하시기 바랍니다.
LightmapMode
주어지면 이 텍스쳐는 렌더러 당 lightmap 파라미터에 의해서 영향을 받을 것입니다. 즉 사용하는 텍스쳐는 재질안에 있을 수 없습니다. 그러나 그것은 렌더러의 세팅으로부터 취해질 수 있습니다. Renderer scripting documentation을 참고하시기 바랍니다.

Example

// EyeLinear texgen mode example
Shader "Texgen/Eye Linear" {
    Properties {
        _MainTex ("Base", 2D) = "white" { TexGen EyeLinear }
    }
    SubShader {
        Pass {
            SetTexture [_MainTex] { combine texture }
        }
    }
} 

----------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------

Render Setup

패스는 그래픽 하드웨어의 다양한 상태를 셋업합니다. 예를 들어 알파 블렌딩이 켜져야 하고 연기가 사용되야 하는 등등. 명령은 이것들과 같습니다:

Material { Material Block }
정점 조명 파이프라인에서 사용하는 재질을 정의합니다. 자세한 내용을 위해서 material page을 참고 합니다.
Lighting On | Off
정점 조명을 켜거나 끄는 것을 세팅합니다. 자세한 내용을 위해서 material page을 참고 합니다.
Cull Back | Front | Off
다각형 culling 모드를 세팅합니다.
ZTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always)
깊이 테스팅 모드를 세팅합니다.
ZWrite On | Off
깊이 쓰기 모드를 세팅합니다.
Fog { Fog Block }
연기 파라미터를 세팅합니다.
AlphaTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always) CutoffValue
알파 테스팅을 합니다.
Blend SourceBlendMode DestBlendMode
알파 블렌딩 모드를 세팅합니다.
Color Color value
정점 조명이 꺼지지 위해서 사용하는 색상을 세팅합니다.
ColorMask RGB | A | 0 | any combination of R, G, B, A
색상 쓰기 마스크를 세팅합니다. ColorMask 0 쓰는 것은 모든 색상 채널로 렌더링하는 것을 끕니다.
Offset OffsetFactor , OffsetUnits
깊이 오프셋을 세팅합니다.
SeparateSpecular On | Off
정점 조명을 위한 별개의 반사적인 색상을 크거나 끕니다. 자세한 내용을 위해서 material page 살펴봅니다.
ColorMaterial AmbientAndDiffuse | Emission
정점 조명을 계산할 때 꼭지점 당 색상을 사용합니다. 자세한 내용을 위해서 material page 살펴봅니다.

 

Texture Setup

SetTexture texture property { [Combine options] }

 

Per-pixel Lighting

픽셀당 조명 파이프라인이 다수의 패스에서 물체를 렌더링하는 것에 의해 작동합니다. Unity는 주변의 그리고 정점 조명을 얻기 위해 물체를 한 번 렌더합니다. 그 후에 그것은 별개의 첨가적인 패스에서 물체에 영향을 주는 각 픽셀 조명을 렌더합니다. 자세한 내용을 위해서는 Render Pipeline 살펴보시기 바랍니다.

Per-vertex Lighting

꼭지점 당 조명은 각 꼭지점을 위해 계산되는 기본적인 Direct3D/OpenGL 조명 모델입니다. 조명은 켜집니다. 조명은 Material block, ColorMaterial 그리고 SeparateSpecular 명령에 의해 영향을 받습니다. 자세한 내용을 위해서는 material page 살펴보시기 바랍니다.

 

----------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------

 

Lighting

Color Color
물체를 단색으로 세팅합니다. 색상은 괄호안의 RGBA 값이거나 또는 사각 괄호안에서 색상 속성 이름입니다.
Material { Material Block }
Material block은 물체의 재질적인 소성을 정의하기 위해서 사용됩니다.
Lighting On | Off
Material block에서 정의된 세팅이 어떠한 효과를 가지기 위해서 사용자는 Lighting On 명령을 가지고 조명을 활성화해야 합니다. 조명이 꺼지면 대신 색상이 Color 명령어로 부터 직접적으로 취해집니다.
SeparateSpecular On | Off
이 명령은 쉐이더의 패스의 끝에 추가될 반사적인 조명을 만들고 반사적인 조명은 텍스쳐링에 영향을 받지 않습니다. Lighting On이 사용될 때의 효과만을 가집니다.

:ColorMaterial AmbientAndDiffuse | 재질에서 세팅된 색상 대신에 사용되는 색상을 만듭니다. AmbientAndDiffuse는 재질의 Ambient와Diffuse값을 대체합니다; 발산은 재질의 발산 값을 대체합니다.

 

 

Material Block

이것은 재질이 조명에 어떻게 반응하는지에 대한 세팅을 포함합니다. 이러한 속성들 중 어떠한 것도 검정을 기본 세팅으로 하는 경우에 남겨지지 않을 수 있습니다 (즉. 효과가 없습니다).

Diffuse Color
확산 색상 컴포넌트. 이것은 물체의 기본 색상입니다.
Ambient Color
주명의 색상 컴포넌트. 이것은 class-RenderSettings에 세팅된 주변 조명 세팅에 의해 그것이 부딪힐 때 물체가 가지는 색상을 의미합니다..
Specular Color
물체의 반적인 하이라이트 색상.
Shininess Number
조명의 날카로움을 0과 1 사이 값으로 표현. 0에서 사용자는 퍼져있는 조명처럼 보이는 커다란 하이라이트를 얻을 것이고 0에서는 아주 작은 얇은 자국을 얻습니다.
Emission Color
어떠한 조명에서도 부딪히지 않을 때 물체의 색상.

Shader "VertexLit" {
    Properties {
        _Color ("Main Color", Color) = (1,1,1,0)
        _SpecColor ("Spec Color", Color) = (1,1,1,1)
        _Emission ("Emmisive Color", Color) = (0,0,0,0)
        _Shininess ("Shininess", Range (0.01, 1)) = 0.7
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Pass {
            Material {
                Diffuse [_Color]
                Ambient [_Color]
                Shininess [_Shininess]
                Specular [_SpecColor]
                Emission [_Emission]
            }
            Lighting On
            SeparateSpecular On
            SetTexture [_MainTex] {
                Combine texture * primary DOUBLE, texture * primary
            }
        }
    }
}

 

----------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------

 

Culling & Depth Testing

 

Cull Back | Front | Off
다각형의 어떤 면이 그려지지 않을 지를 조절합니다.
Back 뷰어로 부터 벗어나 있는 다각형은 그리지 않습니다 (기본 설정).
Front 뷰어를 향하는 다각형은 그리지 않습니다. 물체를 내부로 보낼 때 사용됩니다.
Off culling을 비활성화 – 모든 면을 그립니다. 특별한 효과를 위해서 사용됩니다.
ZWrite On | Off
이 물체로 부터 픽셀들이 깊이 버퍼로 쓰여지는지 여부를 결정 (기본값은On). 사용자가 고체의 물체를 그리고 있다면 이것을 on으로 합니다. 사용자가 반투명한 효과를 그리고 있다면 ZWrite Off 로 바꿉니다. 자세한 내용을 위해서는 아래의 내용을 읽어보시기 바랍니다.
ZTest Less | Greater | LEqual | GEqual | Equal | NotEqual | Always
깊이 테스팅이 어떻게 실행되는지를 나타냅니다. 기본값은 LEqual (기존 물체로서 거리에서 또는 그것으로 부터 물체를 그립니다; 그것들 뒤에서 물체를 숨깁니다).
Offset Factor , Units
사용자가 두 개의 파라미터로 깊이 오프셋을 정하는 것을 허락합니다. factorunitsFactor 는 최대의 Z 기울기를 다각형의 X 또는 Y에 따라 스케일 하고 units은 최소 깊이 버퍼 값을 스케일 합니다. 이것은 사용자가 다각형들이 같은 위치에 있음에도 불구하고 하나의 다각형이 다른 것 위에서 그려지도록 할 수 있습니다. 예를 들어 Offset 0, -1 은 다각형의 기울기를 무시하고 다각형을 카메라 가까이로 당깁니다. 반면 Offset -1, -1 은 방목 각도를 볼 때 심지어 더 가깝게 다각형을 끌어 당깁니다.

 

----------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------

 

Texture block combine command

 

  • Previous 는 이전 SetTexture의 결과입니다.
  • Primarylighting calculation 로부터의 색상이거나 또는 그것이 bound 되어지면 꼭지점 색상입니다.
  • Texture 는SetTexture에서 [TextureName] 에서 지정된 텍스쳐의 색상입니다 (위를 참고하세요).
  • ConstantConstantColor에서 지정된 색상입니다.
  • SetTexture [TexturePropertyName] { Texture Block }ne src1 * src2

    src1과src2를 함께 곱합니다. 결과는 입력값보다 더 어두울 것입니다.
    combine src1 + src2
    src1과src2를 함께 더합니다. 결과는 입력값보다 더 밝을 것입니다.
    combine src1 - src2
    src1에서 src2를 뺍니다.
    combine src1 +- src2
    src1과src2를 함께 더하고나서 0.5를 뺍니다 (부호가 적용되는 덧셈).
    combine src1 lerp (src2) src3
    src2의 알파를 사용해서 src3와src1 사이에서 보간합니다. 보간은 반대 방향임을 주의하시기 바랍니다: 알파가 1일 때src1가 사용되고 알파가 0일 때src3에서 사용됩니다.
    combine src1 * src2 + src3
    src1을src2의 알파 컴포넌트에 곱하고 나서 src3을 더합니다.
    combine src1 * src2 +- src3
    src1을src2의 알파 컴포넌트에 곱하고 나서src3과 함께 부호를 적용하는 덧셈을 합니다.
    combine src1 * src2 - src3
    src1을src2의 알파 컴포넌트에 곱하고 나서src3을 뺍니다.

    모든 src 속성들은 previous, constant, primary 또는 texture 중의 하나일 수 있습니다.

     

    Separate Alpha & Color blending

    기본적으로, 결합 공식은RGB와 색상settexture의 알파 컴포넌트 둘 다를 계산하기 위해서 사용됩니다. 선택적으로 사용자는 알파 계산을 위해서 별개의 공식을 지정할 수 있습니다. 이것은 다음과 같습니다:

    SetTexture [_MainTex] { combine previous * texture, previous + texture }

     

     

    Texture block constantColor command

    ConstantColor color
    결합된 명령에서 사용될 수 있는 상수 색을 정의합니다.

    Texture block matrix command

    matrix [MatrixPropertyName]
    주어진 매트릭스와 함께 이 명령에서 사용된 변형 텍스쳐 좌표.

    Shader "Examples/Self-Illumination 3" {
        Properties {
            _IlluminCol ("Self-Illumination color (RGB)", Color) = (1,1,1,1)
            _Color ("Main Color", Color) = (1,1,1,0)
            _SpecColor ("Spec Color", Color) = (1,1,1,1)
            _Emission ("Emmisive Color", Color) = (0,0,0,0)
            _Shininess ("Shininess", Range (0.01, 1)) = 0.7
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }

        SubShader {
            Pass {
                // Set up basic vertex lighting
                Material {
                    Diffuse [_Color]
                    Ambient [_Color]
                    Shininess [_Shininess]
                    Specular [_SpecColor]
                    Emission [_Emission]
                }
                Lighting On

                // Use texture alpha to blend up to white (= full illumination)
                SetTexture [_MainTex] {
                    constantColor [_IlluminCol]
                    combine constant lerp(texture) previous
                }
                // Multiply in texture
                SetTexture [_MainTex] {
                    combine previous * texture
                }
            }
        }
    }

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

     

    Fog

    Fog { Fog Commands }
    괄호안의fog 명령어를 명세합니다.
    Mode Off | Global | Linear | Exp | Exp2
    Fog 모드를 정의합니다. 기본값은 글로벌입니다. 그것은 렌더링 세팅에서 fog가 켜졌는지 여부에 따라서 Off 또는 Exp2로 번역합니다.
    Color ColorValue
    Fog 색을 세팅합니다.
    Density FloatValue
    기하급수적인 fog를 위한 밀도를 세팅합니다.
    Range FloatValue , FloatValue
    선형 fog를 위해 근거리 그리고 원거리의 범위를 세팅합니다.

    Details

    기본적인 fog 세팅은 Render Settings에 기반합니다: fog 모델은 Exp2 또는 Off 입니다; 세팅으로부터 취해진 밀도 & 색.

    사용자가 fragment programs를 사용한다면 그 쉐이더의 Fog 세팅은 여전히 적용될 것입니다. 고정된 Fog 기능이 없는 플랫폼에서 Unity는 요청되는 Fog 모드를 지원하기 위해서 실시간으로 쉐이더를 패치할 것입니다.

     

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

     

    Alpha testing

     

    AlphaTest Off
    모든 픽셀을 그립니다 (기본 세팅).
    AlphaTest comparison AlphaValue
    그것의 알파 값이 특정 범위안에 있는 픽셀들만 그리기 위한 알파 테스트를 세팅합니다.

    Comparison

    비교는 다음 단어들 중 하나입니다:

    Greater 그것의 알파가 AlphaValue보다 큰 픽셀들만 그립니다.
    GEqual 그것의 알파가’‘AlphaValue’’ 보다 크거나 같은 픽셀들만 그립니다.
    Less 그것의 알파값이’‘AlphaValue’’ 보다 적은 픽셀들만 그립니다.
    LEqual 그것의 알파값이’‘AlphaValue’’ 보다 적거나 같은 픽셀들만 그립니다.
    Equal 그것의 알파값이’‘AlphaValue’’ 과 같은 픽셀들만 그립니다.
    NotEqual 그것의 알파값이’‘AlphaValue’’ 과 다른 픽셀들만 그립니다.
    Always 모든 픽셀을 그립니다. 이것은 AlphaTest Off와 기능적으로 동일합니다.
    Never 어떠한 픽셀도 그리지 않습니다.

    AlphaValue

    0과 1사이의 소수점 숫자. 이것은 기본적인 사각형 타입의 괄호 포맷([변수 이름])을 사용해서 쓰여져야 하는 경우에 하나의 float 또는 범위 속성을 레퍼런스하는 변수를 위해 사용될 수 있습니다.

    Details

    알파 테스트는 투명한 부분들을 가지는 물체를 오목하게 표현할 때 중요합니다. 그래픽 카드는 스크린에 쓰여지는 모든 픽셀의 깊이의 레코드를 유지합니다. 하나의 새로운 픽셀이 이전에 그려진 픽셀보다 멀리 있다면 새로운 픽셀은 디스플레이에 쓰여지지 않습니다. 이것은 Blending과 함께 임에도 불구하고 물체가 들여다 보지 않을 것입니다.

    Shader "Vegetation" {
    Properties {
    _Color ("Main Color", Color) = (.5, .5, .5, .5)
    _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {}
    _Cutoff ("Base Alpha cutoff", Range (0,.9)) = .5
    }
    SubShader {
    // Set up basic lighting
    Material {
    Diffuse [_Color]
    Ambient [_Color]
    }
    Lighting On

    // Render both front and back facing polygons.
    Cull Off

    // first pass:
    //   render any pixels that are more than [_Cutoff] opaque
    Pass {
    AlphaTest Greater [_Cutoff]
    SetTexture [_MainTex] {
    combine texture * primary, texture
    }
    }

    // Second pass:
    //   render in the semitransparent details.
    Pass {
    // Dont write to the depth buffer
    ZWrite off
    // Don't write pixels we have already written.
    ZTest Less
    // Only render pixels less or equal to the value
    AlphaTest LEqual [_Cutoff]

    // Set up alpha blending
    Blend SrcAlpha OneMinusSrcAlpha

    SetTexture [_MainTex] {
    combine texture * primary, texture
    }
    }
    }
    }

     

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

     

    Blending

    Syntax

    Blend Off
    블렌딩 기능 취소
    Blend SrcFactor DstFactor
    블렌딩을 구성 & 활성화. 생성된 색상은 SrcFactor를 곱합니다. 스크린에 이미 있던 색상은 DstFactor 에 의해 곱해지고 두 개는 함께 더해집니다.

    Properties

    모든 다음의 속성들은SrcFactor와DstFactor 둘 다를 위해서 유효합니다. Source 는 계산되어지는 색상을 의미하고 Destination 는 이미 스크린에 있는 색상을 의미합니다.

    One 1의 값 – 소스 또는 데스티네이션 색상이 온전히 오게 합니다.
    Zero 0의 값 – 소스 또는데스티네이션 값을 삭제하게 합니다.
    SrcColor 이 스테이지의 값은 소스 색상 값에 의해 곱해집니다.
    SrcAlpha 이 스테이지의 값은 소스 알파 값에 의해 곱해집니다.
    DstColor 이 스테이지의 값은 프레임 버퍼 소스 색상 값에 의해 곱해집니다.
    DstAlpha 이 스테이지의 값은 프레임 버퍼 소스 알파 값에 의해 곱해집니다.
    OneMinusSrcColor 이 스테이지의 값은 (1 – 소스 색상)에 의해 곱해집니다.
    OneMinusSrcAlpha 이 스테이지의 값은 (1 – 소스 알파)에 의해 곱해집니다.
    OneMinusDstColor 이 스테이지의 값은 (1 – 데스티네이션 색상)에 의해 곱해집니다.
    OneMinusDstAlpha 이 스테이지의 값은 (1 – 데스티네이션 알파)에 의해 곱해집니다.

    Details

    아래는 가장 흔한 블렌드 타입입니다:

    Blend SrcAlpha OneMinusSrcAlpha     // Alpha blending
    Blend One One                       // Additive
    Blend One OneMinusDstColor          // Soft Additive
    Blend DstColor Zero                 // Multiplicative
    Blend DstColor SrcColor             // 2x Multiplicative
    

     

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

    LightMode tag

    LightMode 태그는 조명 파이프라인에서 패스의 역할을 정의합니다. 자세한 내용을 위해서 render pipeline를 참고하시기 바랍니다. 이러한 태그는 수동적으로 거의 사용되지 않습니다; 조명과 상호작용할 필요가 있는 쉐이더는Surface Shaders로서 쓰여지고 그 후에 모든 디테일들이 처리됩니다.

    LightMode 태그를 위한 가능한 값:

    • Always: 항상 렌더됩니다; 조명이 적용되지 않습니다.
    • ForwardBase: Forward rendering에서 사용됩니다, 주변의 주요한 방향성있는 조명과vertex/SH 조명이 적용됩니다.
    • ForwardAdd: Forward rendering에서 사용됩니다; 첨가되는 픽셀당 조명이 적용됩니다, 조명당 한 번의 패스.
    • PrepassBase: Deferred Lighting에서 사용됩니다, normals & specular 대표자를 렌더합니다.
    • PrepassFinal: Deferred Lighting에서 사용됩니다, 텍스쳐, 조명 그리고 방사를 결합해서 마지막 색상을 렌더합니다.
    • Vertex: 물체가 조명에 매핑되지 않을 때 Vertex Lit rendering에서 사용됩니다; 모든 정점 조명이 적용됩니다.
    • VertexLMRGBM: 물체가 조명에 매핑되지 않을 때 Vertex Lit rendering 에서 사용됩니다; lightmap이 RGBM으로 인코딩되는 플랫폼.
    • VertexLM: 물체가 조명에 매핑되지 않을 때 Vertex Lit rendering 에서 사용됩니다; lightmap이double-LDR으로 인코딩되는 플랫폼 (일반적으로 모바일 플랫폼 & 오래된 데스크탑 GPUs).
    • ShadowCaster: 그림자 캐스터로 물체를 렌더합니다.
    • ShadowCollector: Forward 렌더링 경로를 위해서 스크린 공간 버퍼로 물체의 그림자를 모읍니다.

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

     

    Name
    Name "PassName"
    PassName 이름을 현재 패스에게 전달합니다.

    Details

    하나의 패스는 하나의 UsePass 명령이 그것을 레퍼런스할 수 있기 위해서 이름이 주어질 수 있습니다.

     

     

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

     

    BindChannels

    BindChannels 명령은 사용자가 그래픽 하드웨어에 꼭지점 데이터를 어떻게 매핑할지를 정하는 것을 허락합니다.

    BindChannels은 바인딩이 정점 쉐이더 입력값에 따라 조절되는 경우로서 프로그래밍이 가능한 정점 쉐이더가 사용될 때 어떠한 영향도 미치지 않습니다.

    기본적으로 Unity는 사용자를 위한 바인딩을 찾아내나 어떠한 경우에는 사용자가 사용자가 정의한 것이 사용되어지기를 원하기도 합니다.

    예를 들어 사용자는 주요한 UV 세트를 첫 번째 텍스쳐 스테이지에서 사용되기 위해 매핑할 수 있고 부가적인 UV 세트를 두 번째 텍스쳐 스테이지에서 사용되도록 매핑할 수 있습니다. 또는 사용자는 정점 색상이 고려되어져야 하는 것을 하드웨어에 말할 수도 있습니다.

    Syntax

    BindChannels { Bind "source", target }
    정점 데이터 source를 하드웨어 target에 매핑하는 것을 지정합니다.

    Source 다음 중에 하나일 수 있습니다:

    • Vertex: 꼭지점 위치
    • Normal: 꼭지점 normal
    • Tangent: 꼭지점 탄젠트
    • Texcoord: 주요 UV 좌표
    • Texcoord1: 부가적인 UV 좌표
    • Color: 픽셀당 색상

    Target 다음 중에 하나일 수 있습니다:

    • Vertex: 꼭지점 위치
    • Normal: 꼭지점 normal
    • Tangent: 꼭지점 탄젠트
    • Texcoord0, Texcoord1, ...: 해당 텍스쳐 스테이지를 위한 텍스쳐 좌표
    • Texcoord: 모든 텍스쳐 스테이지들을 위한 텍스쳐 좌표들
    • Color: 꼭지점 색상

    Details

    Unity는 어떤 소스가 어떤 타겟에 매핑될 수 있는지에 대한 제한사항들을 가집니다. 소스와 타겟은Vertex, Normal,Tangent 그리고 Color를 위해서 반드시 매치되어야 합니다. 메쉬(TexcoordTexcoord1) 로 부터 텍스쳐 좌표는 텍스쳐 좌표 타겟으로 매핑될 수 있습니다(모든 텍스쳐 스테이지를 위해서는 Texcoord 그리고 특정한 스테이지를 위해서는 TexcoordN).

    BindChannels를 위한 두 가지의 일반적인 사용 케이스가 있습니다:

    • 꼭지점 색상을 고려하는 쉐이더.
    • 두 가지의 UV 세트를 사용하는 쉐이더.

    Examples

    // Maps the first UV set to the first texture stage
    // and the second UV set to the second texture stage
    BindChannels {
       Bind "Vertex", vertex
       Bind "texcoord", texcoord0
       Bind "texcoord1", texcoord1
    } 
    // Maps the first UV set to all texture stages
    // and uses vertex colors
    BindChannels {
       Bind "Vertex", vertex
       Bind "texcoord", texcoord
       Bind "Color", color
    } 

     

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

     

    UsePass
    UsePass "Shader/Name"
    주어진 쉐이더로 부터 주어진 이름과 함께 모든 패스들을 넣으십시오. 쉐이더/이름은 슬래시 기호에 의해 쉐이더의 이름과 패스의 이름을 포함합니다. Shader/Name은 슬래시 기호에 의해 쉐이더의 이름과 패스의 이름을 포함합니다. .

    Details

    쉐이더 중 몇몇은 코드 중복을 감소하면서 다른 쉐이더로 부터 존재하는 패스들을 재사용할 수 있습니다. 예를 들어, 대부분의 픽셀 기반 조명 쉐이더에서 주위의 또는 정점 조명 패스는 상응하는 VertexLit 쉐이더에서 같습니다. UsePass 명령은 또다른 쉐이더로부터 주어진 패스를 포함합니다. 예로서 다음의 명령은 내장된 Specular쉐이더로부터 "BASE"라는 이름의 패스를 사용합니다:

        UsePass "Specular/BASE"
    

    UsePass가 작동하기 위해서는 하나의 이름이 사용자가 사용하기를 원하는 패스로 주어져야 합니다. 패스안에서 Name 명령은 그것에 이름을 줍니다 command inside the pass gives it a name:

        Name "MyPassName"
    

    내부적으로 모든 패스의 이름은 대분자이기 때문에 UsePass는 이름을 반드시 대분자로 참조해야 합니다.

     

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

     

    GrabPass

    GrabPass은 특별한 패스 타입입니다 – 그것은 물체가 하나의 텍스쳐로 그려질 스크린의 내용물을 차지합니다. 이런 텍쳐는 좀 더 발전된 이미지 기반의 효과를 만들기 위해 일련의 하위 패스들에서 사용될 수 있습니다.

    Syntax

    GrabPass는 subshader안에 속합니다. 그것은 두 개의 형식을 취합니다:

    • GrabPass { } 는 텍스쳐로 현재의 스크린 내용을 보낼 것입니다. 텍스쳐는 _GrabTexture_에 의해 앞으로의 패스에서 접근될 수 있습니다. 주의: grab pass의 이 형식은 그것을 사용하는 각 물체를 위해 비용이 많이 드는 스크린 grabbing 오퍼레이션을 할 것입니다!
    • GrabPass { "TextureName" }은 텍스쳐로 스크린 내용을 보낼것이나 주어진 텍스쳐 이름을 사용하는 첫 번째 물체을 위해 프레임당 한 번만 작동할 것입니다. 텍스쳐는 주어진 텍스쳐 이름에 의해서 앞으로의 패스에서 접근될 수 있습니다. 이것은 사용자가 씬에서 grab pass를 사용하는 다수의 물체를 가질 때 더욱 성능이 좋습니다.

    게다가 GrabPass은 NameTags 명령을 사용할 수 있습니다.

    Example

    이것이 이전에 그려졌던 색상을 바꾸는 비용이 많이 드는 방법을 보여줍니다:

    Shader "GrabPassInvert" {
        SubShader {
            // Draw ourselves after all opaque geometry
            Tags { "Queue" = "Transparent" }
    
            // Grab the screen behind the object into _GrabTexture
            GrabPass { }
    
            // Render the object with the texture generated above, and invert it's colors
            Pass {
                SetTexture [_GrabTexture] { combine one-texture }
            }
        }
    } 

    이 쉐이더는 두 가지의 패스를 가집니다: 첫 번째 패스는 렌더링이 될 때 물체의 뒤에 무엇이 있던지 잡아내고 그 후에 두 번째 패스에서 그것을 적용합니다. 물론 지금은 같은 효과가 역blend mode을 사용해서 훨씬 저렴하게 얻어질 수 있습니다.

     

     

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

     

    Fallback

    모든Subshaders후에 Fallback이 정의될 수 있습니다. 그것은 기본적으로 어떠한 서브 쉐이더를 하드웨어 위에서 실행될 수 없으면 또다른 쉐이더로부터의 그것들을 사용하는 것을 시도해보라고 말합니다.

    Syntax

    Fallback "name"
    주어진 이름으로 쉐이더에 대체.
    Fallback Off
    심지어 어떠한 서브 쉐이더가 하드웨어에서 실행될 수 없음에도 명확하게 어떠한 대체도 없고 어떠한 주의 메세지도 프린트되어 지지말아야 한다고 나타냅니다.

    Details

    대체를 나타내는 서술은 마치 그 다른 쉐이더로부터 모든 서브 쉐이더가 그것의 위치에 삽입되어지는 것처럼 같은 효과를 가집니다.

    Example

    Shader "example" {
        // properties and subshaders here...
        Fallback "otherexample"
    } 

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

     

    Category

    Category는 어떠한 명령어들의 논리적인 그룹입니다. 이것은 대체로 렌더링 상태를 "상속"하기 위해 사용됩니다. 예를 들어, 사용자의 쉐이더가 다수의 subshaders를 가지고 그들 각자가 fog를 없애야 하고 추가되는 형태의 blending세팅을 가질지도 모릅니다. 사용자는 그것을 위해서 Category를 사용할 수 있습니다.

    Shader "example" {
    Category {
        Fog { Mode Off }
        Blend One One
        SubShader {
            // ...
        }
        SubShader {
            // ...
        }
        // ...
    }
    }
    

    ----------------------------------------------------------------------------------------------------------------------------------

    ----------------------------------------------------------------------------------------------------------------------------------

     

     

     

     

     

     

     

     

     

     

     

     

     

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    SurfaceShaderLighting  (0) 2012.07.26
    SurfaceShaders  (0) 2012.07.26
    Pass  (0) 2012.07.19
    Category  (0) 2012.07.18
    SubShader Tags  (0) 2012.07.18
    Posted by 프리랜서 디자이너

    ShaderLab syntax: Pass

    Pass 블록은 한 번에 그려지는 물체의 기하학을 야기합니다.

    Syntax

    Pass { [Name and Tags] [RenderSetup] [TextureSetup] }
    기본 패스 명령은 사용하는 텍스쳐의 리스트에 의해 선택적으로 따르는 렌더 셋업 명령의 선택적인 리스트를 포함합니다.

    Name and tags

    패스는 그것의 NameTags의 임의적인 숫자를 정의합니다 – 렌더링 엔진에 패스의 의도를 전달하는 이름/값 스트링.

    Render Setup

    패스는 그래픽 하드웨어의 다양한 상태를 셋업합니다. 예를 들어 알파 블렌딩이 켜져야 하고 연기가 사용되야 하는 등등. 명령은 이것들과 같습니다:

    Material { Material Block }
    정점 조명 파이프라인에서 사용하는 재질을 정의합니다. 자세한 내용을 위해서 material page을 참고 합니다.
     
    Lighting On | Off
    정점 조명을 켜거나 끄는 것을 세팅합니다. 자세한 내용을 위해서 material page을 참고 합니다.
     
    Cull Back | Front | Off
    다각형 culling 모드를 세팅합니다.
     
    ZTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always)
    깊이 테스팅 모드를 세팅합니다.
     
    ZWrite On | Off
    깊이 쓰기 모드를 세팅합니다.
     
    Fog { Fog Block }
    연기 파라미터를 세팅합니다.
     
    AlphaTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always) CutoffValue
    알파 테스팅을 합니다.
     
    Blend SourceBlendMode DestBlendMode
    알파 블렌딩 모드를 세팅합니다.
     
    Color Color value
    정점 조명이 꺼지지 위해서 사용하는 색상을 세팅합니다.
     
    ColorMask RGB | A | 0 | any combination of R, G, B, A
    색상 쓰기 마스크를 세팅합니다. ColorMask 0 쓰는 것은 모든 색상 채널로 렌더링하는 것을 끕니다.
     
    Offset OffsetFactor , OffsetUnits
    깊이 오프셋을 세팅합니다.
     
    SeparateSpecular On | Off
    정점 조명을 위한 별개의 반사적인 색상을 크거나 끕니다. 자세한 내용을 위해서 material page 살펴봅니다.
     
    ColorMaterial AmbientAndDiffuse | Emission
    정점 조명을 계산할 때 꼭지점 당 색상을 사용합니다. 자세한 내용을 위해서 material page 살펴봅니다.

    Texture Setup

    렌더 상태를 셋업한 후에 사용자는 SetTexture 명령을 사용하는 것을 적용하기 위해서 많은 텍스쳐를 지정할 수 있고 그들의 결합 모드도 지정할 수 있습니다:

    SetTexture texture property { [Combine options] }

    텍스쳐 셋업은 고정 함수 멀티텍스쳐링 파이프라인을 구성하고 사용자 정의 fragment shaders 사용되면 무시됩니다.

    Details

    Per-pixel Lighting

    픽셀당 조명 파이프라인이 다수의 패스에서 물체를 렌더링하는 것에 의해 작동합니다. Unity는 주변의 그리고 정점 조명을 얻기 위해 물체를 한 번 렌더합니다. 그 후에 그것은 별개의 첨가적인 패스에서 물체에 영향을 주는 각 픽셀 조명을 렌더합니다. 자세한 내용을 위해서는 Render Pipeline 살펴보시기 바랍니다.

    Per-vertex Lighting

    꼭지점 당 조명은 각 꼭지점을 위해 계산되는 기본적인 Direct3D/OpenGL 조명 모델입니다. 조명은 켜집니다. 조명은 Material block, ColorMaterial 그리고 SeparateSpecular 명령에 의해 영향을 받습니다. 자세한 내용을 위해서는 material page 살펴보시기 바랍니다.

    See Also

    공통적인 기능 또는 다양항 고도의 효과를 구현하기 위한 몇 개의 특별한 패스가 가능합니다:

    • UsePass 또 다른 쉐이더로 부터 이름지어진 패스를 포함합니다.
    • GrabPass 다음의 패스에서의 사용을 위해서 텍스쳐로 스크린의 내용을 얻습니다.

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    SurfaceShaders  (0) 2012.07.26
    한방에 모아보는 레퍼런스  (1) 2012.07.20
    Category  (0) 2012.07.18
    SubShader Tags  (0) 2012.07.18
    GrabPass  (0) 2012.07.18
    Posted by 프리랜서 디자이너
    TA/Unity2012. 7. 18. 17:57
    Shader "Projector/Projector Multiply"
    { 
    Properties
    {
        _Color ("Main Colour", Color) = (1,1,1,0)
        _ShadowTex ("Cookie", 2D) = "gray" { TexGen ObjectLinear }
    }
    
    Subshader
    {
        Tags { "RenderType"="Transparent"  "Queue"="Transparent+100"}
        Pass
        {
            ZWrite Off
            Offset -1, -1
    
            Fog { Mode Off }
    
            //AlphaTest Greater .1
            AlphaTest Less 1
            ColorMask RGB
            Blend One SrcAlpha
    
            SetTexture [_ShadowTex]
            {
                constantColor [_Color]
                combine texture * constant, One - texture
                Matrix [_Projector]
            }
        }
    }
    }
    

    We slightly modified it so that it can take a color and removed the falloff texture, but that's pretty much what you'll find in the Projectors package BlobShadow prefab shader.

    alt text

    Since I want way better control about the way this is all rendered, and since like every sane person I hate fixed-functions shader programming, I wanted to move it to CG code. My puny and failed attempt at simply reproducing what the fixed function shader was doing looks like this:

    'TA > Unity' 카테고리의 다른 글

    TD CameraControl C#  (0) 2013.05.09
    유니티 C# 공부 모음  (0) 2013.05.07
    HLSL 함수  (0) 2012.07.10
    Blending modes..참고 자료  (0) 2012.06.08
    기초적인 조명쉐이더  (0) 2012.06.08
    Posted by 프리랜서 디자이너

    ShaderLab syntax: other commands

    Category

    Category는 어떠한 명령어들의 논리적인 그룹입니다. 이것은 대체로 렌더링 상태를 "상속"하기 위해 사용됩니다. 예를 들어, 사용자의 쉐이더가 다수의 subshaders를 가지고 그들 각자가 fog를 없애야 하고 추가되는 형태의 blending세팅을 가질지도 모릅니다. 사용자는 그것을 위해서 Category를 사용할 수 있습니다.

    Shader "example" {
    Category {
        Fog { Mode Off }
        Blend One One
        SubShader {
            // ...
        }
        SubShader {
            // ...
        }
        // ...
    }
    }
    

    Category 블럭은 쉐이더 구문 분석에만 오직 영향을 미치고 그것은 정확하게그 아래의 모든 불럭으로 Category 내부의 어떤 상태 세팅이던 “pasting”하는 것과 같습니다

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    한방에 모아보는 레퍼런스  (1) 2012.07.20
    Pass  (0) 2012.07.19
    SubShader Tags  (0) 2012.07.18
    GrabPass  (0) 2012.07.18
    UsePass  (0) 2012.07.18
    Posted by 프리랜서 디자이너

    ShaderLab syntax: SubShader Tags

    서브 쉐이더는 그들이 렌더링 엔젠으로 렌더되어질 것이 어떻게 그리고 언제 기대될지를 말하는 태그를 사용합니다.

    Syntax

    Tags { "TagName1" = "Value1" "TagName2" = "Value2" }
    Value1를 가지는 TagName1그리고Value2를 가지는 TagName2 를 지정합니다. 사용자는 사용자가 좋아하는 만큼 많은 태그를 가질 수 있습니다.

    Details

    태그는 기본적으로 키-값 쌍입니다. SubShader 안에서 태그는 렌더링 순서와 서브 쉐이더의 다른 파라미터를 결정하기 위해서 사용됩니다.

    Rendering Order - Queue tag

    사용자는 사용자의 물체가 Queue 태그를 사용해서 그려지는 순서를 결정할 수 있습니다. 쉐이더는 어떠한 투명한 쉐이더라도 그들이 모든 불투명한 물체들 이후에 그려지는 것을 확실시하는 방법으로 어떤 렌더 큐로 물체가 속하는지를 결정합니다.

    4개의 미리 정의된 렌더 큐가 있으나 미리 정의된 것들 사이에는 더 많은 큐가 있을 수 있습니다. 미리 정의된 큐는 다음과 같습니다:

    • Background - 이 렌더 큐는 다른 것들 전에 렌더됩니다. 스카이 박스와 비슷한 것들의 위해 사용됩니다.
    • Geometry (default) - 대부분의 물체를 위해서 사용됩니다. 불투명한 기하가 이 큐를 사용합니다.
    • Transparent - 이 렌더 큐는 기하 이후에 뒤에서 앞으로의 순서대로 그려집니다. 알파 블렌딩되는 어떠한 것(즉. 깊이 버퍼에 쓰여지지 않는 쉐이더)이라도 여기도 가야만 합니다 (유리, 입자 효과).
    • Overlay - 이 렌더 큐는 기하 이후에 뒤에서 앞으로의 순서대로 그려집니다. 알파 블렌딩되는 어떠한 것(즉. 깊이 버퍼에 쓰여지지 않는 쉐이더)이라도 여기도 가야만 합니다 (유리, 입자 효과).
    Shader "Transparent Queue Example" {
         SubShader {
            Tags {"Queue" = "Transparent" }
            Pass {
                // rest of the shader body...
            }
        }
    } 

    투명한 큐에서 렌더하는 법을 설명하는 예

    Geometry 렌더 큐는 최고의 성능을 위해서 물체의 그려지는 순서를 최적화 합니다. 모든 다른 렌더 큐는 물체를 거리에 따라 정렬합니다. 먼 것부터 시작해서 가까운 순으로 그려집니다.

    특별한 사용을 위해서 큐들 사이에서 사용될 수 있습니다. 내부적으로 각각의 큐는 정수 인덱스에 의해 표현됩니다; Background 은 1000, Geometry 는 2000, Transparent 도는 3000 그리고 오버레이는 4000. 쉐이더가 이것과 같은 큐를 사용한다면:

    Tags { "Queue" = "Geometry+1" }
    

    이것은 물체를 모든 불투명 물체 이후에 그러나 투명한 물체를 이전에 렌더 큐 인덱스가 2001일 것처럼 그려지도록 만들 것입니다. 이것은 사용자가 어떠한 물체들을 항상 물체들의 다른 세트들 사이에서 그려지도록 원하는 상황에 유용합니다. 예를 들어, 대부분의 경우에 투명한 물은 불투명한 물체 이후에 그러나 투명한 물체 이전에 그려져야 합니다.

    IgnoreProjector tag

    IgnoreProjector 태그가 주어지고 "True" 값을 가진다면 그 때 이런 쉐이더를 사용하는 물체는 Projectors에 의해 영향을 받지 않을 것입니다. Projectors가 그들에게 영향을 주는 좋은 방법이 없기 때문에 이것은 주로 반투명한 물체들 위에서 유용합니다.

    See Also

    패스에 태그 역시 주어질 수 있습니다. Pass Tags를 살펴보시기 바랍니다.

     

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    Pass  (0) 2012.07.19
    Category  (0) 2012.07.18
    GrabPass  (0) 2012.07.18
    UsePass  (0) 2012.07.18
    BindChannels  (0) 2012.07.18
    Posted by 프리랜서 디자이너

    ShaderLab syntax: GrabPass

    GrabPass은 특별한 패스 타입입니다 – 그것은 물체가 하나의 텍스쳐로 그려질 스크린의 내용물을 차지합니다. 이런 텍쳐는 좀 더 발전된 이미지 기반의 효과를 만들기 위해 일련의 하위 패스들에서 사용될 수 있습니다.

    Syntax

    GrabPass는 subshader안에 속합니다. 그것은 두 개의 형식을 취합니다:

    • GrabPass { } 는 텍스쳐로 현재의 스크린 내용을 보낼 것입니다. 텍스쳐는 _GrabTexture_에 의해 앞으로의 패스에서 접근될 수 있습니다. 주의: grab pass의 이 형식은 그것을 사용하는 각 물체를 위해 비용이 많이 드는 스크린 grabbing 오퍼레이션을 할 것입니다!
    • GrabPass { "TextureName" }은 텍스쳐로 스크린 내용을 보낼것이나 주어진 텍스쳐 이름을 사용하는 첫 번째 물체을 위해 프레임당 한 번만 작동할 것입니다. 텍스쳐는 주어진 텍스쳐 이름에 의해서 앞으로의 패스에서 접근될 수 있습니다. 이것은 사용자가 씬에서 grab pass를 사용하는 다수의 물체를 가질 때 더욱 성능이 좋습니다.

    게다가 GrabPass은 NameTags 명령을 사용할 수 있습니다.

    Example

    이것이 이전에 그려졌던 색상을 바꾸는 비용이 많이 드는 방법을 보여줍니다:

    Shader "GrabPassInvert" {
        SubShader {
            // Draw ourselves after all opaque geometry
            Tags { "Queue" = "Transparent" }
    
            // Grab the screen behind the object into _GrabTexture
            GrabPass { }
    
            // Render the object with the texture generated above, and invert it's colors
            Pass {
                SetTexture [_GrabTexture] { combine one-texture }
            }
        }
    } 

    이 쉐이더는 두 가지의 패스를 가집니다: 첫 번째 패스는 렌더링이 될 때 물체의 뒤에 무엇이 있던지 잡아내고 그 후에 두 번째 패스에서 그것을 적용합니다. 물론 지금은 같은 효과가 역blend mode을 사용해서 훨씬 저렴하게 얻어질 수 있습니다.

    See Also

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    Category  (0) 2012.07.18
    SubShader Tags  (0) 2012.07.18
    UsePass  (0) 2012.07.18
    BindChannels  (0) 2012.07.18
    Name  (0) 2012.07.18
    Posted by 프리랜서 디자이너

    ShaderLab syntax: UsePass

    UsePass 명령은 또다른 쉐이더로 부터의 이름 지어진 패스를 사용합니다.

    Syntax

    UsePass "Shader/Name"
    주어진 쉐이더로 부터 주어진 이름과 함께 모든 패스들을 넣으십시오. 쉐이더/이름은 슬래시 기호에 의해 쉐이더의 이름과 패스의 이름을 포함합니다. Shader/Name은 슬래시 기호에 의해 쉐이더의 이름과 패스의 이름을 포함합니다. .

    Details

    쉐이더 중 몇몇은 코드 중복을 감소하면서 다른 쉐이더로 부터 존재하는 패스들을 재사용할 수 있습니다. 예를 들어, 대부분의 픽셀 기반 조명 쉐이더에서 주위의 또는 정점 조명 패스는 상응하는 VertexLit 쉐이더에서 같습니다. UsePass 명령은 또다른 쉐이더로부터 주어진 패스를 포함합니다. 예로서 다음의 명령은 내장된 Specular쉐이더로부터 "BASE"라는 이름의 패스를 사용합니다:

        UsePass "Specular/BASE"
    

    UsePass가 작동하기 위해서는 하나의 이름이 사용자가 사용하기를 원하는 패스로 주어져야 합니다. 패스안에서 Name 명령은 그것에 이름을 줍니다 command inside the pass gives it a name:

        Name "MyPassName"
    

    내부적으로 모든 패스의 이름은 대분자이기 때문에 UsePass는 이름을 반드시 대분자로 참조해야 합니다.

     

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    SubShader Tags  (0) 2012.07.18
    GrabPass  (0) 2012.07.18
    BindChannels  (0) 2012.07.18
    Name  (0) 2012.07.18
    Fog  (0) 2012.07.18
    Posted by 프리랜서 디자이너

    ShaderLab syntax: BindChannels

    BindChannels 명령은 사용자가 그래픽 하드웨어에 꼭지점 데이터를 어떻게 매핑할지를 정하는 것을 허락합니다.

    BindChannels은 바인딩이 정점 쉐이더 입력값에 따라 조절되는 경우로서 프로그래밍이 가능한 정점 쉐이더가 사용될 때 어떠한 영향도 미치지 않습니다.

    기본적으로 Unity는 사용자를 위한 바인딩을 찾아내나 어떠한 경우에는 사용자가 사용자가 정의한 것이 사용되어지기를 원하기도 합니다.

    예를 들어 사용자는 주요한 UV 세트를 첫 번째 텍스쳐 스테이지에서 사용되기 위해 매핑할 수 있고 부가적인 UV 세트를 두 번째 텍스쳐 스테이지에서 사용되도록 매핑할 수 있습니다. 또는 사용자는 정점 색상이 고려되어져야 하는 것을 하드웨어에 말할 수도 있습니다.

    Syntax

    BindChannels { Bind "source", target }
    정점 데이터 source를 하드웨어 target에 매핑하는 것을 지정합니다.

    Source 다음 중에 하나일 수 있습니다:

    • Vertex: 꼭지점 위치
    • Normal: 꼭지점 normal
    • Tangent: 꼭지점 탄젠트
    • Texcoord: 주요 UV 좌표
    • Texcoord1: 부가적인 UV 좌표
    • Color: 픽셀당 색상

    Target 다음 중에 하나일 수 있습니다:

    • Vertex: 꼭지점 위치
    • Normal: 꼭지점 normal
    • Tangent: 꼭지점 탄젠트
    • Texcoord0, Texcoord1, ...: 해당 텍스쳐 스테이지를 위한 텍스쳐 좌표
    • Texcoord: 모든 텍스쳐 스테이지들을 위한 텍스쳐 좌표들
    • Color: 꼭지점 색상

    Details

    Unity는 어떤 소스가 어떤 타겟에 매핑될 수 있는지에 대한 제한사항들을 가집니다. 소스와 타겟은Vertex, Normal,Tangent 그리고 Color를 위해서 반드시 매치되어야 합니다. 메쉬(TexcoordTexcoord1) 로 부터 텍스쳐 좌표는 텍스쳐 좌표 타겟으로 매핑될 수 있습니다(모든 텍스쳐 스테이지를 위해서는 Texcoord 그리고 특정한 스테이지를 위해서는 TexcoordN).

    BindChannels를 위한 두 가지의 일반적인 사용 케이스가 있습니다:

    • 꼭지점 색상을 고려하는 쉐이더.
    • 두 가지의 UV 세트를 사용하는 쉐이더.

    Examples

    // Maps the first UV set to the first texture stage
    // and the second UV set to the second texture stage
    BindChannels {
       Bind "Vertex", vertex
       Bind "texcoord", texcoord0
       Bind "texcoord1", texcoord1
    } 
    // Maps the first UV set to all texture stages
    // and uses vertex colors
    BindChannels {
       Bind "Vertex", vertex
       Bind "texcoord", texcoord
       Bind "Color", color
    } 

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    GrabPass  (0) 2012.07.18
    UsePass  (0) 2012.07.18
    Name  (0) 2012.07.18
    Fog  (0) 2012.07.18
    AlphaTest  (0) 2012.07.18
    Posted by 프리랜서 디자이너

    ShaderLab syntax: Name

    Syntax

    Name "PassName"
    PassName 이름을 현재 패스에게 전달합니다.

    Details

    하나의 패스는 하나의 UsePass 명령이 그것을 레퍼런스할 수 있기 위해서 이름이 주어질 수 있습니다.

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    UsePass  (0) 2012.07.18
    BindChannels  (0) 2012.07.18
    Fog  (0) 2012.07.18
    AlphaTest  (0) 2012.07.18
    CullAndDepth  (0) 2012.07.18
    Posted by 프리랜서 디자이너

    Fog

    ShaderLab syntax: Fog

    안개 파라미터들은 Fog 명령어로 조절됩니다.

    Fogging은 생성된 픽셀의 색을 카메라로부터의 거리에 따른 일정한 색을 향해 혼합합니다. Fogging은 혼합된 픽셀의 알파 값을 바꾸지 않습니다. 오직 그것의 RGB 컴포넌트만을 바꿉니다.

    Syntax

    Fog { Fog Commands }
    괄호안의fog 명령어를 명세합니다.
    Mode Off | Global | Linear | Exp | Exp2
    Fog 모드를 정의합니다. 기본값은 글로벌입니다. 그것은 렌더링 세팅에서 fog가 켜졌는지 여부에 따라서 Off 또는 Exp2로 번역합니다.
    Color ColorValue
    Fog 색을 세팅합니다.
    Density FloatValue
    기하급수적인 fog를 위한 밀도를 세팅합니다.
    Range FloatValue , FloatValue
    선형 fog를 위해 근거리 그리고 원거리의 범위를 세팅합니다.

    Details

    기본적인 fog 세팅은 Render Settings에 기반합니다: fog 모델은 Exp2 또는 Off 입니다; 세팅으로부터 취해진 밀도 & 색.

    사용자가 fragment programs를 사용한다면 그 쉐이더의 Fog 세팅은 여전히 적용될 것입니다. 고정된 Fog 기능이 없는 플랫폼에서 Unity는 요청되는 Fog 모드를 지원하기 위해서 실시간으로 쉐이더를 패치할 것입니다.

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    BindChannels  (0) 2012.07.18
    Name  (0) 2012.07.18
    AlphaTest  (0) 2012.07.18
    CullAndDepth  (0) 2012.07.18
    SetTexture  (1) 2012.07.17
    Posted by 프리랜서 디자이너

    ShaderLab syntax: Alpha testing

    알파 테스트는 픽셀을 스크린에 쓰여지는 것으로부터 거절할 수 있는 마지막 기회입니다.

    마지막 결과 색상이 계산되어진 후에, 색은 고정 값에 비교되어진 그것의 알파 값을 선택적으로 가질 수 있습니다. 테스트가 실패하면 픽셀은 디스플레이에 쓰여지지 않습니다.

    Syntax

    AlphaTest Off
    모든 픽셀을 그립니다 (기본 세팅).
     
    AlphaTest comparison AlphaValue
    그것의 알파 값이 특정 범위안에 있는 픽셀들만 그리기 위한 알파 테스트를 세팅합니다.

    Comparison

    비교는 다음 단어들 중 하나입니다:

    Greater 그것의 알파가 AlphaValue보다 큰 픽셀들만 그립니다.
    GEqual 그것의 알파가’‘AlphaValue’’ 보다 크거나 같은 픽셀들만 그립니다.
    Less 그것의 알파값이’‘AlphaValue’’ 보다 적은 픽셀들만 그립니다.
    LEqual 그것의 알파값이’‘AlphaValue’’ 보다 적거나 같은 픽셀들만 그립니다.
    Equal 그것의 알파값이’‘AlphaValue’’ 과 같은 픽셀들만 그립니다.
    NotEqual 그것의 알파값이’‘AlphaValue’’ 과 다른 픽셀들만 그립니다.
    Always 모든 픽셀을 그립니다. 이것은 AlphaTest Off와 기능적으로 동일합니다.
    Never 어떠한 픽셀도 그리지 않습니다.

    AlphaValue

    0과 1사이의 소수점 숫자. 이것은 기본적인 사각형 타입의 괄호 포맷([변수 이름])을 사용해서 쓰여져야 하는 경우에 하나의 float 또는 범위 속성을 레퍼런스하는 변수를 위해 사용될 수 있습니다.

    Details

    알파 테스트는 투명한 부분들을 가지는 물체를 오목하게 표현할 때 중요합니다. 그래픽 카드는 스크린에 쓰여지는 모든 픽셀의 깊이의 레코드를 유지합니다. 하나의 새로운 픽셀이 이전에 그려진 픽셀보다 멀리 있다면 새로운 픽셀은 디스플레이에 쓰여지지 않습니다. 이것은 Blending과 함께 임에도 불구하고 물체가 들여다 보지 않을 것입니다.

    이 그림에서 왼쪽에 나무는 AlphaTest를 사용해서 그려집니다. 그것안에 픽셀들이 어떻게 완전히 투명하거나 불투명한지를 참고하시기 바랍니다. 가운데 나무는 오직 Alpha Blending 사용해서 그려집니다. 나뭇 가지 근처의 투명한 부분들이 깊이 버퍼 때문에 어떻게 멀리있는 나뭇잎들을 커버하는지를 참고하시기 바랍니다.

     

     오른쪽에 있는 나무는 마지막 쉐이더 예를 사용해서 그려집니다 – 그것은 어떠한 아티팩트라도 숨기기 위해서 블렌딩과 알파 테스팅이 결합된 것을 구현합니다.

    Examples

    가장 간단한 가능한 예는 알파 채널을 가지는 하나의 텍스쳐를 그것에 지정하는 것입니다. 물체는 알파가 0.5보다 큰 곳에서만 보여질 것입니다.

    Shader "Simple Alpha Test" {
    	Properties {
    		_MainTex ("Base (RGB) Transparency (A)", 2D) = "" {}
    	}
    	SubShader {
    		Pass {
    			// Only render pixels with an alpha larger than 50%
    			AlphaTest Greater 0.5
    			SetTexture [_MainTex] { combine texture }
    		}
    	}
    }

    이것은 그것 스스로 훨씬 좋지 않습니다. 사용자가 조명을 추가하게 해주고 컷오프 값을 조정 가능하게 만들어 줍니다:

    Shader "Cutoff Alpha" {
    	Properties {
    		_MainTex ("Base (RGB) Transparency (A)", 2D) = "" {}
    		_Cutoff ("Alpha cutoff", Range (0,1)) = 0.5
    	}
    	SubShader {
    		Pass {
    			// Use the Cutoff parameter defined above to determine
    			// what to render.
    			AlphaTest Greater [_Cutoff]
    
    			Material {
    				Diffuse (1,1,1,1)
    				Ambient (1,1,1,1)
    			}
    			Lighting On
    			SetTexture [_MainTex] { combine texture * primary }
    		}
    	}
    } 

    식물과 나무를 그릴 때, 많은 게임들은 일반적인 알파 테스팅의 단단한 모서리를 가집니다. 그것에 대한 하나의 방법은 물체를 두 번 그리는 것입니다. 첫 번째 패스에서 사용자는 50% 보다 더욱 불투명한 픽셀만을 그리기 위해서 알파 테스팅을 사용합니다. 두 번째 패스에서 사용자는 픽셀의 깊이를 기록하는 것 없이 잘려진 부분들에 그래픽을 알파 블렌딩 합니다. 사용자는 멀리 있는 나뭇 가지가 가까이 있는 것을 덮어 씌움에 따라 약간의 혼돈을 가질지도 모릅니다. 그러나 실제로 나뭇잎이 그것들 안에 있는 많은 시각적인 디테일을 가지는 것을 보는 것은 어렵습니다.

    Shader "Vegetation" { Properties { _Color ("Main Color", Color) = (.5, .5, .5, .5) _MainTex ("Base (RGB) Alpha (A)", 2D) = "white" {} _Cutoff ("Base Alpha cutoff", Range (0,.9)) = .5 } SubShader { // Set up basic lighting Material { Diffuse [_Color] Ambient [_Color] } Lighting On // Render both front and back facing polygons. Cull Off // first pass: // render any pixels that are more than [_Cutoff] opaque Pass { AlphaTest Greater [_Cutoff] SetTexture [_MainTex] { combine texture * primary, texture } }              // Second pass: // render in the semitransparent details. Pass { // Dont write to the depth buffer ZWrite off // Don't write pixels we have already written. ZTest Less // Only render pixels less or equal to the value AlphaTest LEqual [_Cutoff] // Set up alpha blending Blend SrcAlpha OneMinusSrcAlpha SetTexture [_MainTex] { combine texture * primary, texture } } } }

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    Name  (0) 2012.07.18
    Fog  (0) 2012.07.18
    CullAndDepth  (0) 2012.07.18
    SetTexture  (1) 2012.07.17
    Pass Tags  (0) 2012.07.17
    Posted by 프리랜서 디자이너

    ShaderLab syntax: Culling & Depth Testing

    Culling은 뷰어로부터 방향이 빛나간 다각형들을 그리지 않는 최적화 방법입니다. 모든 다각형은 앞과 뒤쪽 사이드를 가집니다. Culling은 대부분의 물체가 닫혀 있다는 사실을 사용합니다; 사용자가 하나의 정육면체를 가진다면 사용자는 사용자로부터 방향이 빛나가 있는 면은 절대 보지 못할 것입니다 (그것의 앞에 항상 사용자를 마주보는 면이 있습니다). 그래서 사용자는 빛나가 있는 면들은 그릴 필요가 없습니다. 그러므로 그 용어를 사용합니다: Backface culling.

    렌더링을 올바르게 보이게하는 다른 특성은 깊이 테스팅 입니다. 깊이 테스팅은 오직 닫혀진 표면 물체들만이 씬에서 그려지는 것을 확실하게 합니다.

    Syntax

    Cull Back | Front | Off
    다각형의 어떤 면이 그려지지 않을 지를 조절합니다.
    Back 뷰어로 부터 벗어나 있는 다각형은 그리지 않습니다 (기본 설정).
    Front 뷰어를 향하는 다각형은 그리지 않습니다. 물체를 내부로 보낼 때 사용됩니다.
    Off culling을 비활성화 – 모든 면을 그립니다. 특별한 효과를 위해서 사용됩니다.

     

     

    ZWrite On | Off
    이 물체로 부터 픽셀들이 깊이 버퍼로 쓰여지는지 여부를 결정 (기본값은On). 사용자가 고체의 물체를 그리고 있다면 이것을 on으로 합니다. 사용자가 반투명한 효과를 그리고 있다면 ZWrite Off 로 바꿉니다. 자세한 내용을 위해서는 아래의 내용을 읽어보시기 바랍니다.

     

    ZTest Less | Greater | LEqual | GEqual | Equal | NotEqual | Always
    깊이 테스팅이 어떻게 실행되는지를 나타냅니다. 기본값은 LEqual (기존 물체로서 거리에서 또는 그것으로 부터 물체를 그립니다; 그것들 뒤에서 물체를 숨깁니다).

     

    Offset Factor , Units
    사용자가 두 개의 파라미터로 깊이 오프셋을 정하는 것을 허락합니다. factorunitsFactor 는 최대의 Z 기울기를 다각형의 X 또는 Y에 따라 스케일 하고 units은 최소 깊이 버퍼 값을 스케일 합니다. 이것은 사용자가 다각형들이 같은 위치에 있음에도 불구하고 하나의 다각형이 다른 것 위에서 그려지도록 할 수 있습니다. 예를 들어 Offset 0, -1 은 다각형의 기울기를 무시하고 다각형을 카메라 가까이로 당깁니다. 반면 Offset -1, -1 은 방목 각도를 볼 때 심지어 더 가깝게 다각형을 끌어 당깁니다.

    Examples

    This object will render only the backfaces of an object:

    Shader "Show Insides" {
        SubShader {
            Pass {
                Material {
                    Diffuse (1,1,1,1)
                }
                Lighting On
                Cull Front
            }
        }
    } 

    그것을 하나의 정육면체에 적용하도록 하고 사용자가 그것 주위에서 선회할 때 기하학적으로 어떻게 잘못되는지 느끼는 것을 주의하시기 바랍니다. 이것은 사용자가 정육면체 내부의 부분만을 오직 보고 있기 때문입니다.

    Debugging Normals

    다음의 것은 더욱 흥미롭습니다; 첫째로 사용자는 보통의 정점 조명을 가지고 물체를 표현하고 나서 밝은 핑크색으로 뒤쪽 면들을 표현합니다. 이것은 사용자의 normals이 뒤집혀질 필요가 있는 어떤 곳에서는 하이라이팅 효과를 가집니다. 사용자가 어떠한 메쉬에 의해 물려있는 물리적으로 통제되는 물체를 본다면 이 쉐이더를 그들에게 지정하시기 바랍니다. 어떤 핑크색 부분이라도 보이다면 이러한 부분들은 그것을 터치하기에 충분히 불행한 어떠한 곳에서 당겨질 것입니다.

    Here we go:

    Shader "Reveal Backfaces" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" { }
        }
        SubShader {
            // Render the front-facing parts of the object.
            // We use a simple white material, and apply the main texture.
            Pass {
                Material {
                    Diffuse (1,1,1,1)
                }
                Lighting On
                SetTexture [_MainTex] {
                    Combine Primary * Texture
                }
            }
    
            // Now we render the back-facing triangles in the most
            // irritating color in the world: BRIGHT PINK!
            Pass {
                Color (1,0,1,1)
                Cull Front
            }
        }
    } 

    Glass Culling

    Culling을 통제하는 것은 배면을 디버깅하는 것보다 더욱 유용합니다. 사용자가 투명한 물체를 가진다면 사용자는 꽤 자주 물체의 배면을 보여주기는 원합니다. 사용자가 어떠한 culling (Cull Off) 없이 그린다면 사용자가 앞쪽의 면의 어떤 부분에 겹쳐지는 뒤쪽의 면들을 가질 것입니다.

    볼록한 물체(구, 정육면체, 자동차 앞유리)를 위해 작동할 간단한 쉐이더 입니다.

    Shader "Simple Glass" {
        Properties {
            _Color ("Main Color", Color) = (1,1,1,0)
            _SpecColor ("Spec Color", Color) = (1,1,1,1)
            _Emission ("Emmisive Color", Color) = (0,0,0,0)
            _Shininess ("Shininess", Range (0.01, 1)) = 0.7
            _MainTex ("Base (RGB)", 2D) = "white" { }
        }
    
        SubShader {
            // We use the material in many passes by defining them in the subshader.
            // Anything defined here becomes default values for all contained passes.
            Material {
                Diffuse [_Color]
                Ambient [_Color]
                Shininess [_Shininess]
                Specular [_SpecColor]
                Emission [_Emission]
            }
            Lighting On
            SeparateSpecular On
    
            // Set up alpha blending
            Blend SrcAlpha OneMinusSrcAlpha
    
            // Render the back facing parts of the object.
            // If the object is convex, these will always be further away
            // than the front-faces.
            Pass {
                Cull Front
                SetTexture [_MainTex] {
                    Combine Primary * Texture
                }
            }
            // Render the parts of the object facing us.
            // If the object is convex, these will be closer than the
            // back-faces.
            Pass {
                Cull Back
                SetTexture [_MainTex] {
                    Combine Primary * Texture
                }
            }
        }
    } 

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    Fog  (0) 2012.07.18
    AlphaTest  (0) 2012.07.18
    SetTexture  (1) 2012.07.17
    Pass Tags  (0) 2012.07.17
    Color, Material, Lighting (fixed funtion)  (0) 2012.07.12
    Posted by 프리랜서 디자이너

    ShaderLab syntax: Texturing

    기본 꼭지점 조명이 계산되어진 후에 텍스쳐가 적용됩니다. ShaderLab에서 이것은 SetTexture 명령을 사용해서 행해집니다.

    fragment programs이 사용될 때 SetTexture 명령은 어떠한 효과도 가지지 않습니다; 이 경우에서 처럼 픽셀 오퍼레이션은 쉐이더에서 완전히 설명됩니다.

    텍스쳐링은 오래된 스타일 결합 효과를 하는 곳입니다. 사용자는 패스안에서 다수의SetTexture 명령을 가질 수 있습니다 - 페인팅 프로그램의 레이어처럼 모든 텍스쳐가 차례로 적용됩니다. SetTexture 명령은 Pass 끝에 놓여져야만 합니다.

    Syntax

    SetTexture [TexturePropertyName] { Texture Block }
    텍스쳐를 지정합니다. TextureName 은 텍스쳐 속성으로서 정의되어야 합니다. 텍스쳐를 적용하는 방법은 TextureBlock안에서 정의됩니다.

    텍스쳐 블록은 텍스쳐가 어떻게 적용되는지를 조절합니다. 텍스쳐 블록 안에는 세 개의 명령이 있을 수 있습니다: combine, matrix 그리고 constantColor.

    Texture block combine command

    combine src1 * src2
    src1과src2를 함께 곱합니다. 결과는 입력값보다 더 어두울 것입니다.
    combine src1 + src2
    src1과src2를 함께 더합니다. 결과는 입력값보다 더 밝을 것입니다.
    combine src1 - src2
    src1에서 src2를 뺍니다.
    combine src1 +- src2
    src1과src2를 함께 더하고나서 0.5를 뺍니다 (부호가 적용되는 덧셈).
    combine src1 lerp (src2) src3
    src2의 알파를 사용해서 src3와src1 사이에서 보간합니다. 보간은 반대 방향임을 주의하시기 바랍니다: 알파가 1일 때src1가 사용되고 알파가 0일 때src3에서 사용됩니다.
    combine src1 * src2 + src3
    src1을src2의 알파 컴포넌트에 곱하고 나서 src3을 더합니다.
    combine src1 * src2 +- src3
    src1을src2의 알파 컴포넌트에 곱하고 나서src3과 함께 부호를 적용하는 덧셈을 합니다.
    combine src1 * src2 - src3
    src1을src2의 알파 컴포넌트에 곱하고 나서src3을 뺍니다.

    모든 src 속성들은 previous, constant, primary 또는 texture 중의 하나일 수 있습니다.

    • Previous이전 SetTexture의 결과입니다.
    • Primary lighting calculation 로부터의 색상이거나 또는 그것이 bound 되어지면 꼭지점 색상입니다.
    • Texture 는SetTexture에서 [TextureName] 에서 지정된 텍스쳐의 색상입니다 (위를 참고하세요).
    • Constant ConstantColor에서 지정된 색상입니다.

    Modifiers:

    • 위에서 지정된 공식은 색상을 2배 또는 4배 더 밝게 만들기 위해서 Double또는 Quad 키워드에 의해 선택적으로 따라질 수 있습니다.
    • lerp 아규먼트를 제외하고 모든 src속성들은 선택적으로 one - 에 의해서 선택적으로 진행될 수 있습니다 – 결과 색상을 차감되게 하기 위해서.
    • 모든 src 속성들은 오직 알파 채널을 취하기 위해서 alpha 에 의해서 달라질 수 있습니다.

    Texture block constantColor command

    ConstantColor color
    결합된 명령에서 사용될 수 있는 상수 색을 정의합니다.

    Texture block matrix command

    matrix [MatrixPropertyName]
    주어진 매트릭스와 함께 이 명령에서 사용된 변형 텍스쳐 좌표.

    Details

    오래된 그래픽 카드는 텍스쳐에 층을 이루는 방법을 사용합니다. 텍스쳐는 스크린으로 쓰여질 색상을 바꾸면서 각각 이후에 적용된 것입니다. 각 텍스쳐를 위해서 텍스쳐는 일반적으로 이전 오퍼레이션의 결과와 함께 결합됩니다.

     

     

    Separate Alpha & Color blending

    기본적으로, 결합 공식은RGB와 색상settexture의 알파 컴포넌트 둘 다를 계산하기 위해서 사용됩니다.

    선택적으로 사용자는 알파 계산을 위해서 별개의 공식을 지정할 수 있습니다. 이것은 다음과 같습니다:

     

    SetTexture [_MainTex] { combine previous * texture, previous + texture }

     

    여기서 우리는RGB 색을 곱하고 알파를 더합니다.

     

     

     

     

    Specular highlights

    기본적으로 primary색은 확산, 주변의 그리고 반사적인 색상의 합입니다 (Lighting calculation 에서 정의된 것처럼). 사용자가 패스 옵션에서 SeparateSpecular On 을 지정한다면 반사적인 색상은 이전 보다는 결합 계산 후에 반사적인 색상이 더해질 것입니다. 이것은 내장된 정점 조명 쉐이더의 기본적인 기능입니다.

     

     

     

     

    Graphics hardware support

    오래된 그래픽 카드는 텍스쳐 결합 모드를 지원하지 않을지도 모르고 다른 카드는 가능한SetTexture 스테이지의 다른 숫자를 가집니다. 쉐이더 작가는 그 또는 그녀가 지원하고 싶은 카드를 위해서 별개의 SubShaders를 써야 합니다.

    픽셀 쉐이더1.1을 가지는 그래픽 카드는(NVIDIA GeForce 3 and up, ATI Radeon 8500 and up, Intel 9xx) 모든 결합 모드를 지원하고 적어도 4개의 가능한 스테이지를 가집니다. 다음의 테이블은 하드웨어 지원을 요약하고 있습니다:

    Card Stage count Combiner modes not supported
    NVIDIA GeForce 3/4Ti and up 4 Windows 위의 OpenGL에서 src1*src2-src3가 지원되지 않습니다
    NVIDIA TNT2, GeForce 256, GeForce 2, GeForce 4MX 2 Windows 위의 OpenGL에서 src1*src2-src3가 지원되지 않습니다
    ATI Radeon 9500 and up 4-8 OpenGL에서 8, D3D9에서 4
    ATI Radeon 8500-9250 4-6 OpenGL에서 6, D3D9에서 4
    ATI Radeon 7500 3
    ATI Rage 2 src1*src2+src3
    src1*src2+-src3
    src1*src2-src3

    Examples

    Alpha Blending Two Textures

    이 작은 예들은 두 개의 텍스쳐를 취합니다. 첫째로 그것은 _MainTex를 위하기 위해서 첫 번째 결합을 세팅하고 나서 _BlendTex의RGB 색상에서 바래지게 하기 위한 _BlendTex의 알파 채널을 사용합니다.

    Shader "Examples/2 Alpha Blended Textures" {
        Properties {
            _MainTex ("Base (RGB)", 2D) = "white" {}
            _BlendTex ("Alpha Blended (RGBA) ", 2D) = "white" {}
        }
        SubShader {
            Pass {
                // Apply base texture
                SetTexture [_MainTex] {
                    combine texture
                }
                // Blend in the alpha texture using the lerp operator
                SetTexture [_BlendTex] {
                    combine texture lerp (texture) previous
                }
            }
        }
    } 

    Alpha Controlled Self-illumination

    이 쉐이더는 조명이 어디에 적용되는지를 결정하기 위해서 _MainTex의 알파 컴포넌트를 사용합니다. 그것은 두 개의 스테이지들로 텍스쳐를 적용하는 것에 의해 이것을 합니다; 첫 번째 스테이지에서 텍스쳐의 알파 값은 꼭지점 색상과 온전한 하얀색 사이에서 혼합하기 위해서 사용됩니다. 두 번째 스테이지에서 텍스쳐의RGB 값은 곱해집니다.

    Shader "Examples/Self-Illumination" {
        Properties {
            _MainTex ("Base (RGB) Self-Illumination (A)", 2D) = "white" {}
        }
        SubShader {
            Pass {
                // Set up basic white vertex lighting
                Material {
                    Diffuse (1,1,1,1)
                    Ambient (1,1,1,1)
                }
                Lighting On
    
                // Use texture alpha to blend up to white (= full illumination)
                SetTexture [_MainTex] {
                    constantColor (1,1,1,1)
                    combine constant lerp(texture) previous
                }
                // Multiply in texture
                SetTexture [_MainTex] {
                    combine previous * texture
                }
            }
        }
    } 

    우리는 여기서 무료로 어떤 것들을 할 수 있브니다, 그러나 온전하 하얀색과 혼합하는 대신에 우리는 자가 조명 색상을 더하고 그것에 혼합합니다. 속성으로부터 텍스쳐 블렌딩으로 SolidColor을 얻기 위한 ConstantColor의 사용을 참고하시기 바랍니다.

    Shader "Examples/Self-Illumination 2" {
        Properties {
            _IlluminCol ("Self-Illumination color (RGB)", Color) = (1,1,1,1)
            _MainTex ("Base (RGB) Self-Illumination (A)", 2D) = "white" {}
        }
        SubShader {
            Pass {
                // Set up basic white vertex lighting
                Material {
                    Diffuse (1,1,1,1)
                    Ambient (1,1,1,1)
                }
                Lighting On
    
                // Use texture alpha to blend up to white (= full illumination)
                SetTexture [_MainTex] {
                    // Pull the color property into this blender
                    constantColor [_IlluminCol]
                    // And use the texture's alpha to blend between it and
                    // vertex color
                    combine constant lerp(texture) previous
                }
                // Multiply in texture
                SetTexture [_MainTex] {
                    combine previous * texture
                }
            }
        }
    } 

    그리고 마지막으로 우리는 정점 조명의 모든 정점 조명의 속성을 취하고 그것들을 줄입니다:

    Shader "Examples/Self-Illumination 3" {
        Properties {
            _IlluminCol ("Self-Illumination color (RGB)", Color) = (1,1,1,1)
            _Color ("Main Color", Color) = (1,1,1,0)
            _SpecColor ("Spec Color", Color) = (1,1,1,1)
            _Emission ("Emmisive Color", Color) = (0,0,0,0)
            _Shininess ("Shininess", Range (0.01, 1)) = 0.7
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }
    
        SubShader {
            Pass {
                // Set up basic vertex lighting
                Material {
                    Diffuse [_Color]
                    Ambient [_Color]
                    Shininess [_Shininess]
                    Specular [_SpecColor]
                    Emission [_Emission]
                }
                Lighting On
    
                // Use texture alpha to blend up to white (= full illumination)
                SetTexture [_MainTex] {
                    constantColor [_IlluminCol]
                    combine constant lerp(texture) previous
                }
                // Multiply in texture
                SetTexture [_MainTex] {
                    combine previous * texture
                }
            }
        }
    } 

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    AlphaTest  (0) 2012.07.18
    CullAndDepth  (0) 2012.07.18
    Pass Tags  (0) 2012.07.17
    Color, Material, Lighting (fixed funtion)  (0) 2012.07.12
    Performance Tips when Writing Shaders  (0) 2012.07.12
    Posted by 프리랜서 디자이너

    ShaderLab syntax: Pass Tags

    패스는 그들이 렌더링 엔진에 렌더되기를 기대할 때와 어떻게 되는지를 말해주기 위해 태그를 사용합니다.

    Syntax

    :Value1을 가지는 TagName1를 지정하고 Value2를 가지는TagName2를 지정합니다. 사용자는 사용자가 좋아하는 것만큼 많은 태그를 가질 수 있습니다.

    Details

    태그는 기본적으로 키값 쌍들입니다. Pass 내부에서 태그는 이 패스가 조명 파이프라인(주변색, 정점 조명, 픽셀 조명 등.)에서 가지는 역할들과 다른 선택사항들을 조절하기 위해 사용됩니다.

    LightMode tag

    LightMode 태그는 조명 파이프라인에서 패스의 역할을 정의합니다. 자세한 내용을 위해서 render pipeline를 참고하시기 바랍니다. 이러한 태그는 수동적으로 거의 사용되지 않습니다; 조명과 상호작용할 필요가 있는 쉐이더는Surface Shaders로서 쓰여지고 그 후에 모든 디테일들이 처리됩니다.

    LightMode 태그를 위한 가능한 값:

    • Always: 항상 렌더됩니다; 조명이 적용되지 않습니다.
    • ForwardBase: Forward rendering에서 사용됩니다, 주변의 주요한 방향성있는 조명과vertex/SH 조명이 적용됩니다.
    • ForwardAdd: Forward rendering에서 사용됩니다; 첨가되는 픽셀당 조명이 적용됩니다, 조명당 한 번의 패스.
    • PrepassBase: Deferred Lighting에서 사용됩니다, normals & specular 대표자를 렌더합니다.
    • PrepassFinal: Deferred Lighting에서 사용됩니다, 텍스쳐, 조명 그리고 방사를 결합해서 마지막 색상을 렌더합니다.
    • Vertex: 물체가 조명에 매핑되지 않을 때 Vertex Lit rendering에서 사용됩니다; 모든 정점 조명이 적용됩니다.
    • VertexLMRGBM: 물체가 조명에 매핑되지 않을 때 Vertex Lit rendering 에서 사용됩니다; lightmap이 RGBM으로 인코딩되는 플랫폼.
    • VertexLM: 물체가 조명에 매핑되지 않을 때 Vertex Lit rendering 에서 사용됩니다; lightmap이double-LDR으로 인코딩되는 플랫폼 (일반적으로 모바일 플랫폼 & 오래된 데스크탑 GPUs).
    • ShadowCaster: 그림자 캐스터로 물체를 렌더합니다.
    • ShadowCollector: Forward 렌더링 경로를 위해서 스크린 공간 버퍼로 물체의 그림자를 모읍니다.

    RequireOptions tag

    패스는 그것이 외부 상태를 충족할 때만 그려져야 한다는 것을 나타낼 수 있습니다. 이것은 RequireOptions을 사용해서 행해지고 그것의 값은 공간으로 분리된 선택사항의 스트링입니다. 현재적으로 Unity에서 지원되는 선택사항은 다음과 같습니다.

    • SoftVegetation: Soft Vegetation 이 Quality Settings에 오직 있다면 이 패스를 렌더합니다.

    See Also

    SubShaders는 주어진 태그가 주어질 수 있습니다, SubShader Tags를 살펴보시기 바랍니다.

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    CullAndDepth  (0) 2012.07.18
    SetTexture  (1) 2012.07.17
    Color, Material, Lighting (fixed funtion)  (0) 2012.07.12
    Performance Tips when Writing Shaders  (0) 2012.07.12
    Writing vertex and fragment shaders  (0) 2012.07.12
    Posted by 프리랜서 디자이너

    ShaderLab syntax: Color, Material, Lighting

    재질과 조명 파라미터는 내장된 정점 조명을 조절하기 위해 사용됩니다. 정점 조명은 각 꼭지점을 위해서 계산되는 기본적인Direct3D/OpenGL 조명 모델입니다. 조명은 켜집니다. 조명은 Material, ColorMaterial 그리고 SeparateSpecular들에 의해 영향을 받습니다.

    픽셀당 조명은 보통 사용자 정의 vertex/fragment 프로그램과 함께 구현됩니다. 이것들을 위해서 사용자는 여기에 설명된 어떠한 명령도 사용하지 않고 대신 사용자가 모든 조명, 텍스쳐 그리고 다른 것들을 스스로 하는 곳에서 사용자의 자신만의 vertex and fragment programs를 정의합니다.

    꼭지점 컬러링 & 조명은 어떠한 렌더된 기하학을 위해 계산되어진 첫 번째 효과입니다. 그것은 꼭지점 레벨에서 작동하고 텍스쳐가 적용되기 전에 사용된 기본 색상을 계산합니다.

    Syntax

    최고 레벨 명령은 고정 함수 조명을 사용할지 여부 또는 구성 선택 사항들을 조절합니다. 주요 셋업은Material Block 안에 있고 제사한 내용은 아래와 같습니다.

    Color Color
    물체를 단색으로 세팅합니다. 색상은 괄호안의 RGBA 값이거나 또는 사각 괄호안에서 색상 속성 이름입니다.
    Material { Material Block }
    Material block은 물체의 재질적인 소성을 정의하기 위해서 사용됩니다.
    Lighting On | Off
    Material block에서 정의된 세팅이 어떠한 효과를 가지기 위해서 사용자는 Lighting On 명령을 가지고 조명을 활성화해야 합니다. 조명이 꺼지면 대신 색상이 Color 명령어로 부터 직접적으로 취해집니다.
    SeparateSpecular On | Off
    이 명령은 쉐이더의 패스의 끝에 추가될 반사적인 조명을 만들고 반사적인 조명은 텍스쳐링에 영향을 받지 않습니다. Lighting On이 사용될 때의 효과만을 가집니다.

    :ColorMaterial AmbientAndDiffuse | 재질에서 세팅된 색상 대신에 사용되는 색상을 만듭니다. AmbientAndDiffuse는 재질의 Ambient와Diffuse값을 대체합니다; 발산은 재질의 발산 값을 대체합니다.

    Material Block

    이것은 재질이 조명에 어떻게 반응하는지에 대한 세팅을 포함합니다. 이러한 속성들 중 어떠한 것도 검정을 기본 세팅으로 하는 경우에 남겨지지 않을 수 있습니다 (즉. 효과가 없습니다).

    Diffuse Color
    확산 색상 컴포넌트. 이것은 물체의 기본 색상입니다.
    Ambient Color
    주명의 색상 컴포넌트. 이것은 class-RenderSettings에 세팅된 주변 조명 세팅에 의해 그것이 부딪힐 때 물체가 가지는 색상을 의미합니다..
    Specular Color
    물체의 반적인 하이라이트 색상.
    Shininess Number
    조명의 날카로움을 0과 1 사이 값으로 표현. 0에서 사용자는 퍼져있는 조명처럼 보이는 커다란 하이라이트를 얻을 것이고 0에서는 아주 작은 얇은 자국을 얻습니다.
    Emission Color
    어떠한 조명에서도 부딪히지 않을 때 물체의 색상.

    조명에 부딪히는 물체의 전체 새상은 다음과 같습니다:

    Ambient * RenderSettings ambient setting + (Light Color * Diffuse + Light Color * Specular) + Emission

    방정식의 조명 부분은 (괄호 안에) 물체에 부딪히는 모든 조명에 대해서 반복됩니다.

    일반적으로 사용자는Diffuse와Ambient의 색상을 같도록 유지하기를 원합니다 (모든 내장 Unity 쉐이더들도 이것을 합니다).

    Examples

    항상 물체를 순수 빨강색으로 헨더합니다:

    Shader "Solid Red" {
        SubShader {
            Pass { Color (1,0,0,0) }
        }
    } 

    물체를 하얀색으로 칠하는 그리고 정점 조명을 적용하는 기본 쉐이더:

    Shader "VertexLit White" {
        SubShader {
            Pass {
                Material {
                    Diffuse (1,1,1,1)
                    Ambient (1,1,1,1)
                }
                Lighting On
            }
        }
    } 

    Material Inspector에서 visible 속성으로 재질의 색상을 추가하는 확장된 버전입니다:

    Shader "VertexLit Simple" {
        Properties {
            _Color ("Main Color", COLOR) = (1,1,1,1)
        }
        SubShader {
            Pass {
                Material {
                    Diffuse [_Color]
                    Ambient [_Color]
                }
                Lighting On
            }
        }
    } 

    마지막으로 완전히 깃털이 난 정점 조명 쉐이더 (SetTexture 레퍼런스 페이지를 참고해 주세요):

    Shader "VertexLit" {
        Properties {
            _Color ("Main Color", Color) = (1,1,1,0)
            _SpecColor ("Spec Color", Color) = (1,1,1,1)
            _Emission ("Emmisive Color", Color) = (0,0,0,0)
            _Shininess ("Shininess", Range (0.01, 1)) = 0.7
            _MainTex ("Base (RGB)", 2D) = "white" {}
        }
        SubShader {
            Pass {
                Material {
                    Diffuse [_Color]
                    Ambient [_Color]
                    Shininess [_Shininess]
                    Specular [_SpecColor]
                    Emission [_Emission]
                }
                Lighting On
                SeparateSpecular On
                SetTexture [_MainTex] {
                    Combine texture * primary DOUBLE, texture * primary
                }
            }
        }
    } 

    'TA > Unity Shader 레퍼런스' 카테고리의 다른 글

    SetTexture  (1) 2012.07.17
    Pass Tags  (0) 2012.07.17
    Performance Tips when Writing Shaders  (0) 2012.07.12
    Writing vertex and fragment shaders  (0) 2012.07.12
    Blending  (0) 2012.06.25
    Posted by 프리랜서 디자이너