Unity Shader System Introduction

11,460 views

Published on

A brief introduction to unity shader programming.

Published in: Technology
0 Comments
56 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
11,460
On SlideShare
0
From Embeds
0
Number of Embeds
2,380
Actions
Shares
0
Downloads
0
Comments
0
Likes
56
Embeds 0
No embeds

No notes for slide
  • 안녕하십니까? 유니티 테크놀로지스 한국지사의 프로덕트 에반젤리스트로 근무하고 있는 이득우입니다.이번 세션에는 유니티 셰이더 시스템에 대해서 대략적으로 알아보도록 자료를 준비해보았습니다.
  • 이번 발표는 총 3개의 파트로 나누어서 진행됩니다.첫 번째 파트는 유니티 셰이더 시스템 구조에 대해서 설명하고,두 번째 파트는 유니티 렌더링 파이프라인에 대해서 설명합니다.그리고 마지막 세 번째 파트는 유니티 셰이더 프로그래밍에 대해서 설명하겠습니다.
  • 유니티는 모두들 아시다시피 멀티플랫폼 엔진으로 유명합니다.게임을 제작하기 위해서는 CPU와 GPU를 모두 다루어야 하는데, 씨피유(CPU)에서는 모노(MONO)라고 불리는 .NET Framework를 기반으로 멀티플랫폼을 지원합니다.유니티를 조금 살펴보신 분들이라면 이 부분들은 알고 있지 않을까 생각합니다.하지만 다른 반을 차지하는 지피유(GPU)쪽에서 멀티플랫폼을 어떻게 지원하는지는 크게 알려져 있지 않은 것 같습니다.지피유(GPU)에서는 CPU처럼 가상머신 같은 구성을 만들 수 없기 때문에, 유니티에서는 오른쪽의 그림같이 별도의 셰이러랩이라는 추상 스크립트 언어를 사용하여,멀티플랫폼 셰이더를 만들 수 있도록 설계되어 있습니다.
  • 유니티에서는 이러한 스크립트 구조를 셰이더랩이라고 하는데, 말씀드린대로 멀티플랫폼 지원을 위해 고안된 구조입니다.멀티플랫폼을 지원한다는 의미는 어떤 것일까요? 먼저 하드웨어적인 부분을 살펴보면 아이폰 3G와 같은 정말 예전 스마트폰을 지원하는 것에서부터 최신의 스마트폰, 그리고 PC와 각종 콘솔기기들도 모두 지원을 해야합니다.두 번째로는 각 하드웨어에 탑재된 운영체제마다 사용하는 그래픽 라이브러리가 틀리기 때문에,오픈지엘(OpenGL)과 다이렉트X도 지원해야 합니다.마지막으로는 고급 셰이더 개발을 위해 제공되는 언어도 지원해야 합니다. 하나의 문법을 통해 GLSL언어와 Cg, HLSL 언어로 작성한 고급 셰이더 기술도 통일시켜야 합니다.위의 조건을 다 만족시켜야 하므로 멀티플랫폼 셰이더를 만드는 일은 결코 쉽지 않은 일인데, 유니티는 셰이더랩을 통해 하나의 문법으로 이를 모두 호환 가능하게 제공하고 있습니다.
  • 위의 예제는 기본적인 셰이더 랩 구문입니다.셰이더랩의 전체적인 뼈대를 이해하기 위해 아주 간단한 셰이더를 예로 들었는데,붉은 색으로 되어있는 키워드를하나씩 살펴보도록 하겠습니다.
  • 셰이더 키워드는 셰이더의 이름을 결정합니다.지정된 이름은 재질에서 셰이더를 선택할 때 사용되는데, 슬래시(/)를 써서 이름을 구분하면 오른쪽 메뉴 그림과 같이 재질에 셰이더를 설정할 때 다단계로 드롭다운 메뉴로 표시됩니다.
  • 다음은 프로퍼티(Property) 구문입니다.유니티 에디터에서 셰이더에 전달할 다양한 값을 사용자가 편리하게 설정할 수 있도록위의 그림과 같이 다양한 인터페이스를 제공하고 있습니다.특히 슬라이더 인터페이스는 정말 유용한데, 프로그래머가 셰이더를 만들때 프로퍼티를 잘 설계하면,아티스트들이 슬라이더를 통해 값을 조절해서 자기가 원하는 결과가 바로바로 보이게 할 수 있습니다.개인적으로 유니티에서 가장 맘에 드는 기능 중 하나가 아닌가 생각합니다.
  • 지금까지는 유니티 에디터에 관련된 설정이고,이제부터 본격적인 셰이더의 내용을 설정해야하는데,서브셰이더(SubShader)라는 구문이 실제 우리가 생각하는 셰이더라고 보면 됩니다.유니티는 하나의 셰이더에서 다양한 하드웨어를 지원하기 위해 서브셰이더(SubShader)라는 구문을 제공합니다.여러 개의 서브셰이더를 오른쪽과 같이 지정할 수 있는데, 가장 위에 있는 서브셰이더가 먼저 실행이 됩니다.만약에 위에 있는 서브셰이더에 정의된 셰이더 코드가 하드웨어와 호환이 안된다면 다음 서브셰이더가 실행되고,모든 서브셰이더의 구동에 실패하면 폴백(Fallback)에 정의된 셰이더가 대신 실행됩니다.
  • 서브 셰이더는 렌더링을 담당하는 우리가 일반적으로 생각하는 셰이더라고 생각하시면 되며, 여기 그림에서 보는 대로 높은 사양에서는 높은 사양에 맞는 서브셰이더 구문이,낮은 사양에서는 낮은 사양에 맞는 서브 셰이더구문이 실행되어 지오메트리(Geometry)를 렌더링하게 됩니다.
  • 그러면 이제 실제 렌더링을 담당하는 서브 셰이더에 대해서 알아보겠습니다.서브 셰이더 구조는 크게 렌더링의 실행 순서와 설정을 지정하는 태그(Tag)구문과렌더링을 표현하는 패스(Pass) 로 나누어지게 됩니다.유니티는 0번부터 5000번까지 렌더링 순서를 지정하게 구성되어 있는데, 특이하게 숫자가 아닌 이름을 기반으로 이 순서를 지정하게 됩니다.낮은 숫자가 먼저 렌더링되는데, 이 순서는 왼쪽에 보시는대로 숫자가 아닌 키워드로 지정이 있으며, 여기서 +와 –를 더해서 조금 더 구체적으로 순서를 지정할 수 있게 됩니다.
  • 여기 예제는 태그 구문 예제인데, 2000번을 의미하는 Geometry키워드에 +1을 추가하여 20001번째 순서를 지정하였습니다.따라서 이 셰이더를 사용하는 게임 오브젝트는 깊이 정보에 상관없이 아무리 멀리 있더라도, 2000번을가지는 모든 불투명한 물체를 렌더링한 결과를 덮어서 렌더링합니다.
  • 그 다음에 알아볼 것은 지오메트리(Geometry)의 렌더링 방법을 지정하는 패스(Pass) 구문입니다.패스 구문은 여러개를 사용하여 이전 패스에서 나온 결과물을 기반으로 계속 추가적인 표현을 할 수 있습니다.패스 구문은 크게 3가지로 구분되며, 렌더링 설정을 지정하는 패스태그(Pass Tag)구문,GPU의 렌더 스테이트(Render State)를 설정하는 다양한 키워드,마지막으로 실제 셰이더 코드 조각으로 나눌 수 있습니다.
  • 이렇게 패스(Pass) 구문을 통해 물체의 렌더링이 수행되는데, 이 렌더링은 여러분들이 카메라에서 지정한 렌더링방법을 통해 수행됩니다. 이러한 렌더링 방법을 유니티에서는 이를 렌더링 패스(Path) 라고 합니다.이제 이 렌더링 패스에 대해서 알아보겠습니다.
  • 유니티는 현재 버텍스릿,포워드, 디퍼드 라이팅이라 불리는 총 세 가지의 렌더링 방식을 제공합니다.
  • 버텍스 릿은 오래된 하드웨어에서 동작하도록 설계되었습니다. 주로 예전 스마트폰인 아이폰 3G세대로 보면 됩니다.이들 하드웨어의 GPU 성능이 좋지 않기 때문에, 버텍스 별로 라이팅을 계산하고 이를 보간하여 최종 픽셀값을 산출하는 방식으로 동작합니다.이 방식의 장점은 가볍고 빠르다는 것입니다.렌더링 방식이 간단하기 때문에 렌더링 준비를 위해 CPU에서 별도의 작업이 들지 않습니다. 따라서 모바일에서는 최종 결과물의 표현에 문제가 없다면 이 방식을 쓰는 것이 유용하다고 생각합니다.특히 라이트매핑 텍스쳐만 그대로 보여주는 경우 가장 빠르게 동작합니다.단점은 유니티가 제공하는 실시간 렌더링기능을 상당수 지원하지 않습니다.노멀매핑과 같은 표현효과는 물론, 빛의 수, 쿠키, 라이트프로브 등과 같은 기능의 사용이 불가능합니다.
  • 버텍스 릿은 하드웨어 혹은 에디터 설정에 따라 3가지 하나 과정이 진행됩니다.라이트맵이 적용되지 않는 물체에 버텍스를 기반으로 렌더링하는 버텍스 패스 혹은라이트맵을 Double LDR 포맷으로 근사하여 인코딩하여 저장하는 버텍스엘엠(VertexLM) 패스 혹은라이트맵을 RGBM으로 인코딩하여 사용하는 버텍스엘엠알지비엠(VertexLMRGBM) 의 세 가지 중 하나가 실행됩니다.사실 어떤게 쓰일지는 유니티가 자동으로 해주기 때문에 여러분들은 크게 신경쓰지 않아도 됩니다.
  • 두번째는 픽셀당 라이팅을 계산하는 포워드 방식입니다.이전에 비해서 범프매핑을 통해 결과물의 표현이 보다 세밀해진 것을 볼 수 있을 겁니다.
  • 포워드 파이프라인은 다이렉트X 9에 대응하는 가장 일반적인 렌더링 방식입니다.장점은 유니티가 제공하는 렌더링 기능을 대부분 쓸 수 있다는 점이고, 단점은 빛과 물체의 수만큼 계산량이 많아진다는 문제가 있습니다. 그리고 디렉셔널 라이트(Directional Light)에 의한 그림자만 지원을 하는데, 셰이더에 추가 키워드를 넣어서 다른 빛에 의한 그림자도 지원하게 할 수 있습니다.당연하겠지만 복잡한 기능을 구현할 수록 성능은 더 느려지겠지요.
  • 포워드 방식에서 가장 중요한 점은 중요한 빛과 중요하지 않은 빛을 구분하는 일입니다.이는 라이트 컴포넌트 설정에서 직접 지정을 할 수 있는데,중요한 빛은 가장 인텐시티(Intensity)가 높은 디렉셔널 라이트입니다.그리고 라이트 컴포넌트에서 Render Mode가 Important로 설정된 빛입니다.중요한 빛은 품질설정에서 Pixel Light Count에 설정된 수만큼 지정할 수 있으며,나머지는 안중요한 빛이 됩니다. 포워드 방식은 빛의 개수에 따라 계산량이 증가하기 때문에, 이를 설정하는 것은 최적화에 큰 영향을 줍니다.품질 설정의 픽셀 라이트 카운트(Pixel Light Count) 설정이 중요한 빛의 수를 지정하는 일인데,유니티는 중요한 빛은 공들여서 렌더링하고, 안 중요한 빛은 정말 대충~ 렌더링합니다.
  • 위의 예제는 총 8개의 빛 중 중요한 빛을 4개로 설정한 경우입니다. 포워드 방식은 두 가지 방법으로 렌더링되는데, 가장 중요한 빛과 안중요한 빛들을 한번에 처리하는ForwardBase와중요한 빛들을 처리하는 ForwardAdd입니다.
  • 포워드베이스는 중요한 빛과 안중요한 빛들을 한번에 처리하는데비해,포워드애드는 중요한 빛 하나당 한번 렌더링을 수행합니다.따라서 위의 예제의 경우 포워드 베이스에서 A,그리고D부터 H까지 한번 렌더링이 수행되고,B,C,D가 각각 포워드 애드 패스를 통해 렌더링이 수행되어, 총 4번의 렌더링 과정이 진행됩니다.이를 위해 각각의 렌더링 패스에는 필요한 빛의 정보가 변수로 선언되어있습니다.그리고 유니티 엔진은 렌더링이 수행될 때 이 변수에 빛의 정보를 저장해줍니다.
  • 마지막으로 디퍼드 라이팅 파이프라인에 대해서 설명드리겠습니다.모던한 렌더링 파이프라인이라고 할 수 있으며,빛의 수에 제약이 없다는 것이 큰 장점입니다. 그리고 복잡한 씬 렌더링을 배치 작업으로 구현할 수 있다는 장점이 있게 됩니다.단점은 유니티에서는 아직은 모바일에서 사용이 불가능하다는 점이고, 빛은 블린퐁 모델만 지원하며, 투명한 물체를 지원하지 않습니다.
  • 디퍼드 라이팅 렌더링 방식은 무조건 3 단계로 이루어집니다.먼저 카메라에 의해 비춰지는 씬의 지오메트리정보를 수집하여 G버퍼에 저장합니다.이후에는 이 G버퍼를 활용하여 씬에 배치된 라이팅별로 계산을 수행합니다.모든 라이팅 계산이 마무리되면, 마지막으로 라이트맵을 적용하여 다양한 빛의 효과가 적용된 아름다운 최종 결과물을 만들어냅니다.
  • 지금까지는 이러한 유니티가 제공하는 렌더링 방식에 대해서 살펴보았는데, 이제 이러한 환경 속에서 동작하는 셰이더 프로그래밍에 대해서 알아보도록 합시다.
  • 유니티는 프로그래밍을 구현하는 방식도 결코 단순하지가 않습니다.크게 여기서 보이는 세 가지 방식을 지원합니다.유니티는 고정 함수(Fixed Function) 프로그램, 버텍스 프래그먼트(Vertex Fragment) 프로그램, 서피스 셰이더(Surface Shader) 프로그램의 세 가지를 제공하고 있습니다.
  • 고정 함수 프로그램은 버텍스 릿 렌더링 방식에 적합한 프로그램 방법입니다.하드웨어 대상을 1. 버젼대의 셰이더 모델을 사용한다는 가정을 전제로 하기 때문에, 고급 언어를 통해서 프로그래밍이 불가능하기 때문에, 대신유니티는 SetTexture등과 같은 여러가지 키워드를 제공하고 있습니다.위의 셰이더 코드는 두 개의 텍스쳐를 활용하여 다양한 효과를 주는 간단한 예시입니다.심플하지만 빠르기 때문에, 모바일에서는 퀄리티에만 문제가 없다면 성능을 위해 사용을 고려해보는 것도 좋다고 생각합니다.
  • 두 번째 방법은 버텍스 프래그먼트 프로그램은 가장 일반적으로 많이 사용하는 셰이더 프로그래밍이라고 할 수 있습니다.아까 보여드린 Pass구문에 셰이더 코드를 넣을 수 있게 설계되어 있는데,명확히 어떤 언어를 쓸 것인지 유니티에 알려줘야 합니다.이를 위해 유니티는 CGPROGRAM 혹은 GLSLPROGRAM이라는 키워드를 제공합니다.
  • 예를들면 같은 결과를 내는 셰이더를 Cg로 만들때와 GLSL로 만들때의 예시입니다.
  • 유니티는 두 가지 언어를 모두 지원하지만,여러분들이 멀티플랫폼 셰이더를 만들려고 한다면 Cg를 사용해야합니다.여러분들이 셰이더랩 문법으로 셰이더 코드를 Cg로 만들어주면, 최종 HLSL 셰이더 코드가 만들어지게 되고,내부 변환기에 의해서 HLSL코드를 GLSL로 자동으로 변환됩니다.이때 현재까지 변환으로 인한 성능 저하 사례를 발견되지 않은 것으로 알고 있습니다.이렇게 변환된 GLSL 코드는 유니티가 축적한 노하우인 GLSL 옵티마이저(Optimizer) 를 통해 두번 최적화되어 최종 셰이터 코드로 완성됩니다.따라서 Cg로 짠 셰이더코드도 OpenGL에서 동작하는 것이 가능해집니다.
  • 이렇게 멀티플랫폼 셰이더 코드 제작을 위한 모든 준비가 갖추어 졌지만 문제가 또 한가지 남아있습니다.하나의 셰이더 프로그램을 만들려는데, 여러분들이 유니티 에디터에서 설정한 기능들까지 적용되도록 다양한 경우를 생각해야한다는 겁니다.예를 들면 라이트의 형태가 디렉셔널인지, 포인트 형태인지, 라이트매핑은 사용을 했는지이런 것들까지 다 감안을 하여 셰이더 코드를 작성해야 합니다.이를 위해 유니티는 전처리기 구문을 제공하고 있지만, 범용적인 일반 셰이더를 만드는데 132줄이나 사용되게 되는 문제점들이 있습니다.
  • 이러한 문제를 해결하기 위해서 고안된 프로그래밍 방식이 서피스 셰이더 프로그램입니다.서피스 셰이더 프로그램을 사용하면 코드의 양을 크게 줄일 수 있습니다.위의 예는 서피스 셰이더 프로그램을 사용하여 132줄 짜리 범용 디퓨즈(Diffuse) 라이팅 셰이더를 12줄로 줄인 예입니다.
  • 서피스 셰이더가 이렇게 단순한 이유는 엔진에서 자동으로 버텍스 프래그먼트 셰이더 코드로 자동으로 변환해주기 때문입니다.마치 물에 떠 있는 오리를 보면 평화롭지만 이를 위해 쉴새 없이 발을 움직이는 것과 비슷하다고 볼 수 있습니다.여러분들은 오리 몸통처럼 편하게 서피스 셰이더 코드를 짜시면, 유니티가 발이 되서 바쁘게 버텍스/프래그먼트 셰이더로 변환해줍니다..
  • 서피스 셰이더 프로그래밍은 크게 표면처리와 빛처리의 두 단계로 나누어집니다. 서피스 셰이더 프로그램의 제작을 위해 위 명령어와 같이 유니티 엔진에게 나는 서피스 셰이더 방식을 통해서 셰이더를 개발한다고 알려줘야 합니다.이를 위해 먼저 #pragma surface로 선언해야 합니다.두 번째는 표면을 처리하는 함수의 이름을 알려주고 세 번째는 빛을 처리하는 함수를 알려주어야 합니다.
  • 표면을 설정하는 방법은 유니티가 제공하는 서피스 아웃풋(SurfaceOutput)이라는 구조에 적절한 값을 넣어주면 됩니다.아티스트들이 셰이더 개발에 많이 활용하는 셰이더FX와 같은 노드 기반의 그래픽 셰이더 프로그래밍 툴과 유사하다고 생각하실 겁니다.
  • 두번째는 라이팅 모델의 적용인데, 유니티가 제공하는 블린퐁 혹은 램버트 공식을 쓰고 싶다면 함수이름에 단순히 Lambert, BlinnPhone이라고만 적어주면 됩니다.이 라이팅 모델은 유니티 설치 폴더내의 Lighting.cginc에 정의되 있습니다.만약에 직접 라이팅 모델을 만들고 싶다면 Lighting으로 시작하는 함수를 만들고 입력값과 출력값만 맞추어주면 됩니다.오른쪽의 예제는 램프 라이팅을 적용한 예제인데, LightingRamp라는 이름의 함수를 제작하고, 위의 Lambert 대신에 Ramp라는 이름으로 바꾼 결과입니다.
  • 이렇게 만들어진 서피스 셰이더 프로그램은 자동으로 버텍스 /프래그먼트 셰이더로 변환됩니다.이 과정이 궁금하다고요?제가 정말 유니티 셰이더 개발에 가장 효과적인 팁을 하나 알려드리겠습니다.지금까지 제가 설명한거 다 까먹어도 됩니다.지금 보여드리는 이 키워드만 기억하시고 집으로 가셔도 좋습니다. 서피스 셰이더 코드에 #pragma debug라는 코드를 하나 추가해주십시요.그러면 어떻게 유니티가 서피스 셰이더 프로그램을 버텍스/프래그먼트 프로그램으로 변환하는지 알 수가 있을 겁니다.제가 직접 시연으로 보여드리겠습니다.
  • 이 복잡한 변환된 코드를 모두 다 설명드릴 수는 없고, 파악에 도움이되는 두 가지만 설명드릴까 합니다.먼저 패스 구문 아래의 태그 구문인데, 태그에 라이트모드와 렌더링 공정이름을 적어주면, 여러분이 제작한 셰이더 코드는 태그에서 지정된 렌더링 파이프라인에서 실행됩니다.다시 기억을 더듬어서 포워드 렌더링 방식을 꺼내보겠습니다.포워드베이스와 포워드애드의 두 가지 렌더링 파이프라인이 있다고 말씀드렸었죠?
  • 유니티에는 잘 안알려지지 않는 예외 사항이 있는데,라이트맵이 없는 상황에서,포워드 렌더링을 수행할 때, 셰이더에 FowardAdd태그가 중요한 빛이라 할지라도 4개의 빛이 ForwardBase로 들어가서 버텍스 방식으로 렌더링 됩니다.
  • 그러면 데모를 보여드리겠습니다.씬을 보면 1개의 중요한 디렉셔널 라이트와 4개의 중요한 포인트라이트로 렌더링되고 있습니다.일반적으로 렌더링하면가장 중요한 빛 1번, 나머지 중요한 빛 4번이 각각 렌더링 되어 총 5번의 드로우콜이 발생합니다.이번에는 ForwardAdd를 지정하지 않는 셰이더를 만들고 이를 반영해보겠습니다.품질에는 그다지 큰 차이가 없는데, 드로우콜은 1로 줄어든 것을 볼 수 있습니다.
  • 두 번째는 알아두시면 좋은 것은 키워드인데, 이 키워드를 통해 다양한 상황에 따라 여러 셰이더들을 적용하게 됩니다.아까 코드를 보시면 셰이더 키워드들에 따라 수 많은 조합의 셰이더가 정의된 것을 볼 수 있습니다. 엔진에서 자체적으로 지정한 키워드들이 있는데, 우리가 직접 키워드를 정의할 수도 있습니다.
  • 위의 프래그마 코드를 통해 키워드를 직접 만들어 넣을 수 있습니다.이들은 여러분의 셰이더 코드에 전처리기 구문으로 이를 활용할 수 있습니다.이렇게 키워드가 반영되는 셰이더 코드를 만들면,마지막으로 스크립트에서 Shader.EnableKeyword함수를 통해 키워드가 활성시키면 활성화된 키워드 부분이 실행됩니다.데모를 보여드리겠습니다.
  • 지금까지 유니티 셰이더의 구조에 대한 기초적인 설명을 마쳤는데, 많은 도움이 되셨는지 궁금하네요.이 외에도 안 다룬 기능들이 몇 가지 있지만 이 정도로 마치고자 합니다.향후 궁금한 점들은 제 이메일이나 페이스북으로 문의주시면 되겠습니다.감사합니다.
  • Unity Shader System Introduction

    1. 1. Unity Shader System李 得 雨 (Dustin Lee)Unity Technologies KoreaProduct Evangelist
    2. 2. Session IntroductionPart 1 : Unity Shader StructurePart 2 : Unity Rendering PipelinePart 3 : Unity Shader ProgrammingSession Introduction
    3. 3. Unity Shader Structure
    4. 4. Unity Multi Platform ArchitectureUnity Shader StructureCPU GPUUser Script(C#, UnityScript )Virtual MachineUnity EngineUser Shader Script(ShaderLab)Script ParserNative Shader
    5. 5. Shader Script ( Shader Lab )Unity Shader Structure• Abstract shader script layer for multiplatform system• Multi-Device• Supports old mobile hardwares. ( DX 7/8 )• Support modern mobile hardwares ( DX9, Shader Model 2 )• Support PC and Console hardwares (Shader Model 3 )• Supports Extreme PC hardware ( DX11, Shader Model 5 )• Multi-Library• OpenGL , OpenGL E/S , DirectX• Multi-Language• GLSL , Cg, HLSL
    6. 6. Shader Lab SyntaxUnity Shader StructureSimple Custom Shader ExampleShader "Custom/Simple" {Properties{_MainTex ("Base (RGB)", 2D) = "white" {}}SubShader{Tags { "Queue"="Geometry+1" }Pass{SetTexture [_MainTex] { combine texture }}}FallBack "Diffuse"}
    7. 7. Shader Lab Syntax ( Shader )Unity Shader Structure• Defines shader name• “/” seperates drop down levelShader "Custom/Simple"
    8. 8. Shader Lab Syntax ( Properties )Unity Shader Structure• Define list of parameters for artist.• Float textbox• Float Range Slides• Vector4 textboxes• Color Picker• 2D Texture ( POT )• 2D Texture ( NPOT )• Cube Texture
    9. 9. Shader Lab Syntax ( SubShader )Unity Shader Structure• An unity shader is designed to supportmulti devices with each subshadercode• Top-down priority order• If all subshaders fail, unity runsfallback shaderSubShader{// First Priority Shader Code( Designed for high-level PC )}SubShader{// Second Priority Shader Code( Designed for mid-level PC )}SubShader{// Third Priority Shader Code( Designed for low-level PC )}// Alternative Shader CodeFallback “VertexLit”
    10. 10. Unity Rendering PipelineUnity Shader StructureGame ObjectGeometryHigh QualitySubShaderLow QualitySubShaderApplyUnity Shader
    11. 11. SubShader Format ( Tag )Unity Shader StructureTagPassSubShader• SubShader Tag Keyword• how and when shader runs?• When is very important!• Background = 1000• Geometry = 2000• AlphaTest = 2450• Transparent = 3000• Overlay = 4000
    12. 12. Unity Rendering PipelineUnity Shader StructureSubShaderTags { "Queue"="Geometry+1" }Unity renders this game object after rendering ofall other opaque game objects.
    13. 13. SubShader Format ( Pass )Unity Shader Structure• SubShader Pass Keyword• Performs rendering of the geometry• Subshader can have multiple passes.• Pass consists of three divisions• Pass Tag• Render State• Shader CodePassRender StateShader Code SnippetCullingDepthTestAlphaTestBlendingPass Tag
    14. 14. Unity Rendering PipelineUnity Shader StructureGame ObjectFor the actual rendering operation,unity engine provides three rendering methods.
    15. 15. Unity Rendering Pipeline
    16. 16. Unity Rendering PipelineUnity Rendering Pipeline• Vertex Lit• Forward• Deferred Lighting
    17. 17. Vertex Lit PipelineUnity Rendering Pipeline• Designed for old hardware.• DirectX 7 / 8 compatible• Final pixel is calculated by interpolation between vertices.• Pros• Simple and Fast• No overhead in CPU side• Useful to lightmapping in mobile• Cons• Cookie, Lightprobe, Shadow are not available.• Number of light has limit.• Can’t express per-pixel expression. ex) normal mapping
    18. 18. Vertex Lit Pipeline PassUnity Rendering Pipeline• There are 3 options for vertex lit pipeline• 1 pass is chosen by unity setting or hardware detection.• Vertex Pass• Just simple vertex lit mode.• No lightmap support.• VertexLM Pass• For old smartphone.• Encodes lightmap by Double LDR .• VertexLMRGBM Pass• For modern smartphone.• Encodes lightmap by RGBM.
    19. 19. Forward PipelineUnity Rendering PipelineVertex Lit Forward
    20. 20. Forward PipelineUnity Rendering Pipeline• Common rendering pipeline• DirectX 9• Per-pixel calculation• Pros• Lightprobe, cookie, shadow are available.• Can render object by independent lighting model.• Cons• Lighting computation increases linearly by number of lights• Only directional light support shadow.• Unity supports additional shader keyword-> fullforwardshadows
    21. 21. Light Setting in Forward PipelineUnity Rendering Pipeline• Render Mode Setting in Light component• Important Light• The largest intensity directional light• Uses in per-pixel calculation• Pixel Light Count• Not Important Light• Next 4 lights use for per-vertex calculation.• Rest lights are approximated by SH (Spherical Harmonics)
    22. 22. Forward Pipeline PassUnity Rendering Pipeline• Rendering is performed by 2 passes• ForwardBase• A ( Most important light )• D~H• ForwardAdd• B, C, D ( Important lights )
    23. 23. Forward Pipeline PassUnity Rendering PipelineForwardBaseForwardAdd_WorldSpaceLightPos0unity_4LightPosX0/Y0/Z0unity_LightColor[4]_WorldSpaceLightPos0• 4 Per Pixel Count = 4 Draw Calls per object1 ForwardBase ( A, D, E, F, G, H ) + 3 ForwardAdd ( B, C, D )
    24. 24. Deferred Lighting PipelineUnity Rendering Pipeline• Modern rendering pipeline• Pros• No number of light limit.• Useful to complex scene rendering at once.• Cons• Mobile doesn’t support this currently.• Supports only Blinn-Phong lighting model.• Does’t support transparent object.-> Only forward supports transparent objects.
    25. 25. Deferred Lighting Pipeline PassUnity Rendering PipelineIn Unity, three rendering passes happen in deferred lighting pipeline.PrePassBase PrePassLighting PrePassFinalRenderTexture Main _CameraNormalsTexture_CameraDepthTexture_LightBufferG Buffer
    26. 26. Shader Programming
    27. 27. Unity Shader ProgramingUnity Shader Programming• Fixed Function Program• Vertex / Fragment Program• Surface Shader Program
    28. 28. Fixed Function ProgramUnity Shader Programming• Matches vertex lit rendering pipeline• Shader model 1.x• Provides special keywords for rendering operation.Pass {Material {Diffuse [_Color]Ambient [_Color]Shininess [_Shininess]Specular [_SpecColor]Emission [_Emission]}Lighting OnSeparateSpecular OnSetTexture [_MainTex] {combine previous * texture}SetTexture [_BlendTex] {combine previous lerp (texture) texture}}
    29. 29. Vertex / Fragment ProgramUnity Shader Programming• Common shader programming• Unity provides keywords for coding snippet area-> CGPROGRAM , GLSLPROGRAMPass {CGPROGRAM#pragma vertex vert#pragma fragment fragfloat4 vert(float4 inVert : POSITION) : SV_POSITION{float4 outVert = mul (UNITY_MATRIX_MVP, inVert);return outVert;}half4 frag(float4 i) : COLOR{return half4(1.0, 0.0, 0.0, 1.0);}ENDCG}Native Code
    30. 30. Cg vs GLSLUnity Shader ProgrammingGLSL CodeCg CodeCGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct v2f {float4 pos : SV_POSITION;float3 color : COLOR0;};v2f vert (appdata_base v) {v2f o;o.pos = mul (UNITY_MATRIX_MVP,v.vertex);o.color = v.normal * 0.5 + 0.5;return o;}half4 frag (v2f i) : COLOR {return half4 (i.color, 1);}ENDCGGLSLPROGRAMvarying vec4 position;#ifdef VERTEXvoid main(){position = gl_Normal * 0.5 + vec4(0.5, 0.5, 0.5, 0.0);gl_Position = gl_ModelViewProjectionMatrix* gl_Vertex;}#endif#ifdef FRAGMENTvoid main(){gl_FragColor = position;}#endifENDGLSLResult
    31. 31. HLSL to GLSL Shader ParserUnity Shader Programming• If you use Cg, unity converts to all platform shader codes automatically.Cg/HLSLCode SnippetHLSLShader CodeFullHLSL CodeCovertedGLSL CodeOptimized GLSLShader CodeFinal GLSLShader CodeFull Shader Code PreprocessorProcessingHLSL to GLSL Converter1st Optimizationhttps://github.com/aras-p/glsl-optimizer2nd Optimizationhttps://github.com/aras-p/hlsl2glslfork
    32. 32. Problem in Vertex/Fragment ProgramUnity Shader Programming• What happens if we try to program rendering code?• Lightmapping Setting• Type of Light ( Directional, Point, Spot )• Unity provides various predefined processor. but this make complex.#ifdef LIGHTMAP_OFFfloat3 shlight = ShadeSH9 (float4(worldN,1.0));o.vlight = shlight;#ifdef VERTEXLIGHT_ONfloat3 worldPos = mul(_Object2World, v.vertex).xyz;o.vlight += Shade4PointLights (unity_4LightPosX0, unity_4LightPosY0, unity_4LightPosZ0,unity_LightColor[0].rgb, unity_LightColor[1].rgb, unity_LightColor[2].rgb,unity_LightColor[3].rgb, unity_4LightAtten0, worldPos, worldN );#endif // VERTEXLIGHT_ON#endif // LIGHTMAP_OFFRequires 132 lines of code for general multi-platform diffuse shader
    33. 33. Surface Shader ProgramUnity Shader Programming• Simplified version of vertex/fragment program by unity way.• Automatically converts vertex/fragment code for various situations.CGPROGRAM#pragma surface surf Lambertsampler2D _MainTex;struct Input {float2 uv_MainTex;};void surf (Input IN, inout SurfaceOutput o) {half4 c = tex2D (_MainTex, IN.uv_MainTex);o.Albedo = c.rgb;o.Alpha = c.a;}ENDCG#ifdef LIGHTMAP_OFFfloat3 shlight = ShadeSH9 (float4(worldN,1.0));o.vlight = shlight;#ifdef VERTEXLIGHT_ONfloat3 worldPos = mul(_Object2World, v.vertex).xyz;o.vlight += Shade4PointLights (unity_4LightPosX0, unity_4LightPosY0,unity_4LightPosZ0,unity_LightColor[0].rgb, unity_LightColor[1].rgb,unity_LightColor[2].rgb,unity_LightColor[3].rgb, unity_4LightAtten0, worldPos,worldN );#endif // VERTEXLIGHT_ON#endif // LIGHTMAP_OFF132 lines of code12 lines of code
    34. 34. Surface Shader ProgramUnity Shader ProgrammingYourSurface ShaderProgramVertex/FragmentProgram
    35. 35. Surface Shader Program StructureUnity Shader Programming• Shader Programming = Surface Code + Light CodeSet Function forSurface SettingUnity Lighting ModelOrCustom Lighting Model#pragma surface surf LambertSurface Program
    36. 36. Surface Shader Program 1st StepUnity Shader Programming• Set proper value to each member of structure.• Similar with graphical shader programming interfacestruct SurfaceOutput{fixed3 Albedo;fixed3 Normal;fixed3 Emission;half Specular;fixed Gloss;fixed Alpha;};
    37. 37. Surface Shader Program 2nd StepUnity Shader ProgrammingLambert BlinnPhong RampUnity PredefinedLighting Mode( Lighting.cginc )CustomLighting Modelhalf4 LightingRamp (SurfaceOutput s, half3lightDir, half atten) {half NdotL = dot (s.Normal, lightDir);half diff = NdotL * 0.5 + 0.5;half3 ramp = tex2D (_Ramp,float2(diff)).rgb;half4 c;c.rgb = s.Albedo * _LightColor0.rgb *ramp * (atten * 2);c.a = s.Alpha;return c;}_Ramp Texture
    38. 38. Surface Shader Program FinalUnity Shader Programming#pragma debug• Unity generates vertex / fragment shader program code
    39. 39. LightMode TagUnity Shader ProgrammingSurface generates shader code for each lightmode automatically.ForwardBaseForwardAddPass {Tags { “LightMode"=“ForwardBase" }…• ForwardBase• Most important light• Not important light• ForwardAdd• Other Important lights
    40. 40. LightMode HackUnity Shader Programming• No Lightmap• No ForwardAdd LightMode defined4 important lights passes into ForwardBase passConditionDemo1 Directional + 4 Important Point Lights
    41. 41. ComparisonUnity Shader ProgrammingCommon Shader5 DrawcallsForwardBase Only Shader1 Drawcall
    42. 42. Shader KeywordsUnity Shader ProgrammingUnity classifies shaders based on keywords for multi-platforms and multi-environmentsPredefined Keywords• DIRECTIONAL , POINT , SPOT• LIGHTMAP_(ON/OFF), DIRLIGHTMAP_(ON/OFF), VERTLIGHT_(ON/OFF)• SHADOW_(ON/OFF), POINT_COOKIE, DIRECTIONAL_COOKIE …
    43. 43. User Defined KeywordUnity Shader ProgrammingCGPROGRAM#pragma multi_compile MAKE_REDMAKE_NOT_RED…..void surf (Input IN, inout SurfaceOutput o) {#ifdef MAKE_REDhalf4 c = half4(1,0,0,1);#elsehalf4 c = half4(0,1,0,1);#endifo.Albedo = c.rgb;o.Alpha = c.a;}ENDCGShader.EnableKeyword(“MAKE_RED”);#pragma multi_compileDemo
    44. 44. Thank you!Email : dustin@unity3d.comFacebook : MrDustinLee

    ×