Skip to content

Unity ShaderLab

JungSu Kim edited this page Jan 26, 2016 · 1 revision

Syntax

  • ShaderLab Grammer
Shader "name" { [Properties] Subshaders [Fallback] [CustomEditor] }

ShaderLab:Properties

  • Unity의 Material Inspector에서 설정가능한 파라미터 목록을 정의 할 수 있음

  • 2D Texture, Cubemap, 3D (Volume) 속성을 정의할 수 있음

  • ShaderLab:Properties Grammer

// 기본문법
Properties { Property [Property ...] }
 
// Numbers and Sliders
name ("display name", Range (min, max)) = number
name ("display name", Float) = number
name ("display name", Int) = number
 
// Colors and Vectors
name ("display name", Color) = (number,number,number,number)
name ("display name", Vector) = (number,number,number,number)
 
// Textures
name ("display name", 2D) = "defaulttexture" {}
name ("display name", Cube) = "defaulttexture" {}
name ("display name", 3D) = "defaulttexture" {}
ShaderLab:Properties Example
// properties for a water shader
Properties
{
    _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) = "" {}
}

Property attributes and drawers

  • 쉐이더 코드에서 프로퍼티 속성으로 보여지는 부분의 모습을 설정할 수 있음
  • http://docs.unity3d.com/kr/current/ScriptReference/MaterialPropertyDrawer.html
    • [HideInInspector] - does not show the property value in the material inspector.
    • [NoScaleOffset] - material inspector will not show texture tiling/offset fields for texture properties with this attribute.
    • [Normal] - indicates that a texture property expects a normal-map.
    • [HDR] - indicates that a texture property expects a high-dynamic range (HDR) texture.
    • [Gamma] - indicates that a float/vector property is specified as sRGB value in the UI (just like colors are), and possibly needs conversion according to color space used. See Properties in Shader Programs.
    • [PerRendererData] - indicates that a texture property will be coming from per-renderer data in the form of a MaterialPropertyBlock. Material inspector changes the texture slot UI for these properties.
    • [Range] - indicates that a float range
    • [KeywordEnum] - indicates that a key world to number
    • [Enum] - indicates that a enum object
    • [Toggle] - indicates that a toggle
// ShaderLab Property Attributes and Drawer
Shader "Custom/Example" {
    Properties {
        [HideInInspector] _MainTex ("Base (RGB)", 2D) = "white" {}
        [NoScaleOffset] _NormalTex ("Normal", 2D) = "white" {}
 
        // 키워드 순서대로 0, 1, 2의 숫자를 전달해줌
        [KeywordEnum(None, Add, Multiply)] _Overlay ("Overlay mode", Float) = 0
        [Enum(UnityEngine.Rendering.BlendMode)] _SrcBlend ("Src Blend", Float) = 0
 
        _OverlayTex ("Overlay", 2D) = "black" {}
 
        // Display as a toggle.
        [Toggle] _Invert ("Invert color?", Float) = 0
    }
    // rest of shader code...
}

ShaderLab:SubShader

  • Unity는 메쉬를 그릴 때, 사용할 쉐이더를 찾아 사용자의 그래픽 카드에서 실행되는 서브쉐이더(SubShader)를 선택함

  • 실행가능한 서브쉐이더(SubShader)가 없을때는 Fallback에 정의된 쉐이더가 선택됨

  • ShaderLab:SubShader Basic Grammer

// 기본 문법
Subshader { [Tags] [CommonState] Passdef [Passdef ...] }
 
// 예제
// 이 서브 쉐이더는 하나의 패스를 정의하고, 모든 라이팅을 끄고 단순히 _MainTex라는 이름의 텍스처를 가진 메쉬를 표시합니다.
SubShader {
    Pass {
        Lighting Off
        SetTexture [_MainTex] {}
    }
}

SubShaders & Fallback

  • 위에서부터 하나씩 실행해서 하나라도 실행되면 종료되며, 아무것도 실행할 수 없다면 Fallback에 지정한 셰이더를 실행함
// SubShaders & Fallback
Shader "My Shader"
{
    // 이 셰이더가 실행되지 않으며 다음 SubShader로 이동
    SubShader
    {
        // Hight Quality Shading
    }
     
    // 이 셰이더가 실행되지 않으며 다음 SubShader로 이동
    SubShader
    {
        // Mid Quality Shading
    }
 
    // 이 셰이더가 실행되지 않으며 다음 SubShader로 이동
    SubShader
    {
        // Low Quality Shading
    }
 
    // 아무런 SubShader도 실행되지 않으면 "Diffuse"가 실행됨
    Fallback "Diffuse"
}

SubShader & Pass

  • Material이나 Shader에서 Pass를 지정하지 않으면 첫 Pass부터 차례대로 실행됨
// Subshader & Pass
Shader "My Shader"
{
    SubShader
    {
        Pass
        {
            Tags { "Queue" = "Opaque" }
            // some shading
        }
 
        Pass
        {
            Tags { "Queue" = "Transparent" }
            // some shading
        }
    }
}

ShaderLab:Pass

  • 지오메트리(Geometry)를 한번만 렌더링하게 지정해 줌
// 문법
Pass {[Name and Tags] [RenderSetup] }
 
// Render State Setup
// Cull
Cull Back | Front | Off
 
// ZTest
ZTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always)
 
// ZWrite
ZWrite On | Off
 
// Blend
Blend SourceBlendMode DestBlendMode
Blend SourceBlendMode DestBlendMode, AlphaSourceBlendMode AlphaDestBlendMode
 
// ColorMask
ColorMask RGB | A | 0 | any combination of R, G, B, A
 
// Offset
Offset OffsetFactor, OffsetUnits
 
// Fixed Function Lighting and Material
Lighting On | Off
Material { Material Block }
SeparateSpecular On | Off
Color Color-value
ColorMaterial AmbientAndDiffuse | Emission
 
// Fixed Function Fog
Fog { Fog Block }
 
// Fixed Function AlphaTest
AlphaTest (Less | Greater | LEqual | GEqual | Equal | NotEqual | Always) CutoffValue
 
// Fixed Function Texture Combiners
SetTexture textureProperty { combine options }

ShaderLab:Culling & Depth Testing

  • http://docs.unity3d.com/Manual/SL-CullAndDepth.html

  • Cull Back | Front | Off

    • Back Don’t render polygons facing away from the viewer (default).
    • Front Don’t render polygons facing towards the viewer. Used for turning objects inside-out.
    • Off Disables culling - all faces are drawn. Used for special effects.
  • ZWrite On | Off

    • Controls whether pixels from this object are written to the depth buffer (default is On).
    • If you’re drawng solid objects, leave this on. If you’re drawing semitransparent effects, switch to ZWrite Off. For more details read below.
  • ZTest Less | Greater | LEqual | GEqual | Equal | NotEqual | Always

    • How should depth testing be performed. Default is LEqual (draw objects in from or at the distance as existing objects; hide objects behind them).

ShaderLab:Blending

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

ShaderLab:Pass Tags

Tags { "TagName1" = "Value1" "TagName2" = "Value2" }
  • LightMode

    • Always: Always rendered; no lighting is applied.
    • ForwardBase: Used in Forward rendering, ambient, main directional light, vertex/SH lights and lightmaps are applied.
    • ForwardAdd: Used in Forward rendering; additive per-pixel lights are applied, one pass per light.
  • Deferred: Used in Deferred Shading; renders g-buffer.

  • ShadowCaster: Renders object depth into the shadowmap or a depth texture.

  • PrepassBase: Used in legacy Deferred Lighting, renders normals and specular exponent.

  • PrepassFinal: Used in legacy Deferred Lighting, renders final color by combining textures, lighting and emission.

  • Vertex: Used in legacy Vertex Lit rendering when object is not lightmapped; all vertex lights are applied.

  • VertexLMRGBM: Used in legacy Vertex Lit rendering when object is lightmapped; on platforms where lightmap is RGBM encoded (PC & console).

  • VertexLM: Used in legacy Vertex Lit rendering when object is lightmapped; on platforms where lightmap is double-LDR encoded (mobile platforms).

ShaderLab:Stencil

ShaderLab:Name

ShaderLab:Legacy Lighting

http://docs.unity3d.com/Manual/SL-Material.html

ShaderLab:Legacy Texture Combiners

http://docs.unity3d.com/Manual/SL-SetTexture.html

ShaderLab:Legacy Alpha Testing

http://docs.unity3d.com/Manual/SL-AlphaTest.html

ShaderLab:Legacy Fog

http://docs.unity3d.com/Manual/SL-Fog.html

ShaderLab:Legacy BlindChannels

http://docs.unity3d.com/Manual/SL-BindChannels.html

ShaderLab:UsePass

  • 다른 쉐이더에서 명명된 패스를 사용할 수 있음
  • 기존 쉐이더의 패스를 이용하기 때문에 코드 중복이 줄어듬
// 문법
UsePass "Shader/Name"
 
// 예제
// 내장 VertexLit/SHADOWCASTER 패스를 사용함
UsePass "VertexLit/SHADOWCASTER"
 
// UsePass로 지정된 패스 사용
Name "MyPassName"

ShaderLab:GrabPass

구매한 BlendMode 변경하는 에셋에서 GrabPass를 사용해서 구현함 특별한 패스 타입으로, 그려질 화면의 내용을 텍스처 내에 잡아둠, 이 텍스처는 후속 프로세스에서 고급 이미지 기반의 효과에 사용할 수 있음 SubShader안에 존재해야 하며 아래와 같이 두 형식 중 하나를 취함 GrabPass {}로 지정하고, 단순히 현재 화면 내용을 텍스처 내에 잡아둠. 이 텍스처는 후속 패스에서 _GrabTexture 이름으로 엑세스할 수 있음 GrabPass {"TextureName"}를 통해 화면 내용을 텍스처 내에 잡고 있지만, 프레임마다 딱 한 번, 지정 텍스처 이름을 사용하는 첫 번째 오브젝트 분에만 실시함. 텍스처는 후속 패스로 지정된 텍스처 이름으로 액세스 할 수 있음. 씬에서 GrabPass를 사용하는 오브젝트가 여러 개 있는 경우에 효율적인 방법임 GrabPass안에 Name 및 Tags 명령을 사용할 수 있음

// 문법
GrabPass {} or GrabPass {"TextureName"}
 
// 예제
// 이전에 렌더링된 색상을 반전하는 방법(비용이 비싼 방법) -> 같은 효과를 더 저렴하게 invert blend mode를 사용하여 구현할 수 있음
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 the colors
        Pass
        {
            SetTexture [_GrabTexture] { combine one-texture }
        }
    }
}

ShaderLab:SubShader Tags

  • 언제 어떻게 렌더링 엔진에서 렌더링 할 지 지정함
// ShaderLab:SubShader Tags
// 문법
Tags { "TagName1" = "Value1" "TagName2" = "Value2" }
 
// Rendering Order - Queue tag
// Background
// Geometry(default)
// AlphaTest
// Transparent
// Overlay
Shader "Transparent Queue Example"
{
     SubShader
     {
        Tags { "Queue" = "Transparent" } // Tags { "Queue" = "Geometry+1" }
        Pass
        {
            // rest of the shader body...
        }
    }
}
 
// RenderType tag
 
// DisableBatching tag
 
// ForceNoShadowCasting tag
 
// IgnoreProjector tag
 
// CanUseSpriteAtlas tag
 
// PreviewType tag

ShaderLab:Fallback

  • 모든 SubShader의 구문을 시도후 현재 하드웨어에서 실행할 수 있는 쉐이더가 없는 경우 시도할 쉐이더를 지정해 줄 수 있음
// ShaderLab:Fallback
// 문법
Fallback "name" or Fallback Off
 
// 예제) 모든 SubShader를 실행 할 수 없으면 Diffuse를 실행함
Shader "example" {
  SubShader {
  }
 
  SubShader {
  }
 
  Fallback "Diffuse"
}

ShaderLab:CustomEditor

  • Shader에 CustomEditor를 정의할 수 있음. 이 쉐이더를 사용하는 모든 머티리얼은 이 인스펙터를 사용함
// ShaderLab:CustomEditor
// 문법
CustomEditor "name"
 
// 예제) 이 쉐이더는 MyCustomEditor를 사용함
Shader "example" {
    // properties and subshaders here...
    CustomEditor "MyCustomEditor"
}

ShaderLab:Category

  • Category안의 명령을 논리적으로 그룹화 한 것. 이것은 렌더링 상태를 상속하는 데 사용함
  • 예를들어, 쉐이더에 여러 SubShader가 있는 경우, 각각 Fog를 off하고, blending을 추가로 지정해야 하는데 Category를 사용하면 쉽게 처리할 수 있음
// SubShader:Category
// 예제) Category 그룹안의 SubShader에 Fog Off, Blend One One을 지정해 줌
Shader "example" {
  Category {
    Fog { Mode Off }
    Blend One One
    SubShader {
        // ...
    }
    SubShader {
        // ...
    }
    // ...
  }
}

심화된 쉐이더 랩관련 주제들(Advanced ShaderLab topics)

유니티 렌더링 파이프라인(Unity's Rendering Pipeline)

렌더링 패스(Rendering Paths)

http://docs.unity3d.com/kr/current/Manual/Rendering-Tech.html 쉐이더의 어떤 Pass에 라이팅이 어떻게 적용되는지는 어느 Rendering Pass가 사용되는지에 따라 결정됨. 쉐이더의 각 패스는 Pass Tags를 통해, 그 라이팅 유형과 통신함

포워드 렌더링 패스(Forward Rendering Pass)

http://docs.unity3d.com/kr/current/Manual/RenderTech-ForwardRendering.html ForwardBase와 ForwardAdd패스가 사용됨 ForwardBase 패스는 ambient, 라이트 맵, 기본 디렉셔널 라이트 및 중요하지 않은(vertex/SH) 라이트를 한번에 렌더링 함 ForwardAdd 패스는 추가적인 픽셀 당 라이트에 사용됨 만약 포워드 렌더링이 사용되지만, 쉐이더가 forward-suitable 패스(ForwardBase와 ForwardAdd 어느 쪽도)를 가지지 않으면, 그 오브젝트는 Vertex Lit 패스에서 렌더링 됨

디퍼드 쉐이딩 패스(Deferred Shading Pass)

http://docs.unity3d.com/Manual/RenderTech-DeferredShading.html 디퍼드 패스는 빛에 필요한 모든 정보를 렌더링 함(Built-in Shader의 diffuse color, specular color, smoothness, world space normal, emission) 또한 Emission Channel에 라이트 맵, 반사 프로브 및 주변 조명 정보를 추가 함

레거시 디퍼드 라이팅 패스(Legacy Deferred Lighting Pass)

http://docs.unity3d.com/Manual/RenderTech-DeferredShading.html PrepassBase 패스는 Vertex와 반사 지수를 렌더링 함 PrepassFinal 패스는 텍스처, 라이팅 및 방출 메테리얼 프로퍼티를 결합함으로써 최종적인 색상을 렌더링 함 일반적인 씬 내의 라이팅은 모든 씬 공간에서 개별적으로 이루어 짐

레거시 버텍스 릿 렌더링 패스(Legacy Vertex Lit Rendering Pass)

  • 정점 라이팅은 프로그램 가능한 Vertex 패스는 라이트 맵이 사용되지 않은 오브젝트에 사용됨.
  • 모든 라이트는 고정 함수 OpenGL/Direct3D 라이팅 모델(Blinn-Phong)을 사용하여 한 번에 렌더링 함
  • VertexLMRGBM 패스는 라이트 맵이 RGBM 인코딩된 경우, 라이트맵 사용 오브젝트에 사용됨(PC와 콘솔). 실시간 라이팅은 적용되지 않음. 패스는 텍스처와 라이트맵의 결합에 사용됨
  • VertexLMM 패스는 라이트맵이 double-LDR로 인코딩된 경우, 라이트맵 사용 오브젝트에 사용됨(모바일). 실시간 라이팅은 적용되지 않음. 패스는 텍스처와 라이트맵의 결합에 사용됨

Graphics Command Buffers을 활용하여 렌더링 파이프라인을 확장 할 수 있음

쉐이더 작성시 성능 팁(Performance Tips when writing Shaders)

필요한 것만 계산한다(Use Common Sense)

  • 실제 필요없는 것은 모두 생략하고 필요한 것만 계산한다
  • 예를 들어, 각 메테리얼마다의 색상을 지원하는 쉐이더를 유연하게 하는건 좋지만, 항상 색상이 흰색이라면, 화면에서 정점 또는 픽셀 당 렌더링을 위해 계산하는 것은 낭비임
  • 또 염두에 두어야 할 것은 계산의 빈도임. 일반적으로 픽셀이 정점보다 많이 렌더링되며, 정점이 오브젝트보다 많이 렌더링 된다.
  • 따라서 가능하다면, 픽셀 쉐이더 계산을 정점 쉐이더로 이동 또는 쉐이더에서 계산을 완전히 제외하고 스크립트에서 값을 설정하도록 해야함

범용 표면 쉐이더 사용을 줄인다(Less Generic Surface Shaders)

  • Surface Shaders은 라이팅과 상호 작용하는 쉐이더를 쓰는 경우에 우수합니다. 그러나 이러한 기본 옵션은 "일반적인 경우"를 위해 켜져 있습니다. 많은 경우, 이 것들을 조정하는 것으로 쉐이더의 실행을 빨리하거나 최소할 수 있음
    • approxview : 뷰 방향을 사용하는 쉐이더(Specular)에 있어, 각 픽셀마다가 아닌 정점마다 뷰 방향을 정규화합니다. 대략적인 값이지만, 보통 이것으로 충분함
    • hafsview : Specular 쉐이더 유형을 더 빠르게 합니다. Half-vector (라이팅 방향과 뷰 벡터의 중간)이 계산되어 정점마다 표준화 된, * 라이팅 함수(lighting function)은 미리 중간 벡터를 뷰 벡터 대신 인수로 받습니다.
    • noforwardadd : Forward Rendering에서 지향성 라이트만 완벽하게 지원합니다. 나머지 라이트는, 정점 라이트와 구면 조화(spherical harmonics) 효과를 계속 표현할 수 있습니다. 이것은 쉐이더를 작게 만들며, 여러 라이트가 존재하고 있어도 항상 하나의 패스로 렌더링 됩니다.
    • noambient : 쉐이더의 ambient 라이팅 및 구면 조화를 무효화 함. 이에 따라 약간 빨라짐

계산의 정확도를 예측한다(Precision of computations)

  • Cg/HLSL에서 쉐이더를 쓰는 경우, 세개의 기본적인 수치 유형이 있음. float, half, fixed
    • float : 높은 정밀도의 부동 소수점 숫자입니다. 일반적으로 32비트, 즉 일반적인 프로그래밍 언어의 float와 동일.
    • half : 중간 정밀도의 부동 소수점 숫자입니다. 일반적으로 16비트, –60000에서 +60000까지 십진수로 3.3 자리의 정밀도.
    • fixed : 낮은 정밀도의 고정 소수점 수. 보통 11비트, –2.0에서 +2.0까지 1/256의 정확성.
  • 가능한 낮은 정밀도를 사용하는것이 모바일 플랫폼에는 특히 중요함
  • 색상과 단위 길이 벡터에 대해서는 fixed, 범위와 정밀도가 충분하다면 half를 사용하고, 그렇지 않으면 float를 사용함
  • 대부분의 모바일 GPU는 낮은 정밀도(fixed/lowp)에 swizzle 연산을 적용하는 것은 고가입니다. 마찬가지로 fixed/lowp로 높은 정리도 유형의 변환은 상당히 고가입니다.

알파 테스팅(Alpha Testing)

  • 고정 함수(Fixed Function)의 AlphaTest 또는 프로그래머블에 해당하는 요소인 clip()은 다른 플랫폼에서 다른 퍼포먼스 특성을 나타냄 일반적으로 대부분의 플랫폼에서 완전히 투명한 픽셀을 컬링하는 것은 작은 이점이 있습니다.
  • 그러나, iOS 및 일부 Android 장치에서 볼 수 있는 PowerVR GPU에서 알파 테스트는 고가입니다.

칼라 마스크(Color Mask)

  • 대부분의 iOS와 Android 장치에서 볼 수 있는 모바일 GPU는 ColorMask를 사용하여 채널을 제외하는 것은 고가이며, 정말 필요한 경우에만 사용하세요.

렌더링 시에 쉐이더 교체(Rendering with Replaced Shaders)

Replacement shaders

  • 일부 렌더링 효과는 다른 세트의 쉐이더를 사용하여 씬을 렌더링해야 합니다.
  • 예를 들어, 뛰어난 엣지 검출에는, 표면의 차이가 다른 엣지를 검출하기 위해, 씬에 법선이 있는 텍스처가 필요합니다.
  • 다른 효과에서도 씬에 깊이가 있는 텍스처가 필요하기도 합니다. 이것을 달성하기 위해 씬을 모든 오브젝트를 Replaced 쉐이더로 렌더링 할 수 있습니다.
  • 쉐이더 replacement를 스크립팅으로 수행하기 위해서는 Camera.RenderWithShader 또는 Camera.SetReplacementShader 함수를 사용합니다. 두 함수는 shader와replacementTag를 사용합니다.
  • 카메라는 씬을 평소대로 렌더링합니다. 오브젝트는 메테리얼을 사용하지만, 실제로 사용되는 쉐이더가 변경됩니다.
  • replacementTag가 비어 있으면, 씬의 모든 오브젝트는 지정된 Replaced Shader에서 렌더링됩니다.
  • replacementTag가 비어 있지 않은 경우, 렌더링 된 각 오브젝트에 대해 :
  • The real object’s shader is queried for the tag value.
  • If it does not have that tag, object is not rendered.
  • A subshader is found in the replacement shader that has a given tag with the found value. If no such subshader is found, object is not rendered.
  • Now that subshader is used to render the object.
  • 만약 모든 쉐이더가 예를 들어, “RenderType” 태그 값에 “Opaque”, “Transparent”, “Background”, “Overlay”가 있었을 경우, 불투명한 오브젝트만 렌더링하는 Replacement Shader를 RenderType=Solid tag인 하나의 서브 쉐이더를 사용하여 설명할 수 있습니다.
  • 다른 태그의 유형은 Replacement Shader에서 찾을 수 없기 때문에, 오브젝트는 렌더링되지 않습니다.
  • 또는 복수의 서브 쉐이더를 다른 “RenderType”의 태그 값을 위해, 기술할 수 있습니다. 공교롭게도 모든 Unity 내장 쉐이더는 “RenderType” 태그 세트를 가지고 있습니다.

Lit Shader replacement

  • Shader Replacement를 사용하면 씬은 카메라에 설정된 렌더링 패스를 사용하여 렌더링됩니다.
  • 즉, Replacement에 사용되는 쉐이더는 그림자 및 라이팅 패스를 포함할 수 있다는 것입니다(표면 쉐이더를 Shader Replacement에 사용할 수 있습니다). 이것은 특수 효과의 렌더링 및 씬의 디버깅에 유용합니다.

Unity 내장 쉐이더에서의 Replacement Shader 태그

  • Opaque: 대부분의 쉐이더 (Normal](shader-NormalFamily.html), Self Illuminated, Reflective, Terrain 쉐이더).
  • Transparent: 대부분의 부분적으로 투명한 쉐이더(Transparent, 파티클, 글꼴, Terrain 추가 패스 쉐이더).
  • TransparentCutout: 마스킹 된 투명 쉐이더(Transparent Cutout, 2 패스 식물 쉐이더).
  • Background: Skybox 쉐이더.
  • Overlay: GUITexture, 후광(Halo), 플레어 쉐이더(Flare shaders).
  • TreeOpaque: Terrain 엔진 나무 껍질.
  • TreeTransparentCutout: Terrain 엔진 나뭇잎.
  • TreeBillboard: Terrain 엔진 빌보드 Tree.
  • Grass: terrain 엔진의 grass.
  • GrassBillboard: Terrain 엔진 빌보드 Grass.

사용자 정의 쉐이더 GUI(Custom Shader GUI)

  • 머테리얼 인스펙터에 보여지는 GUI를 사용자가 재정의하여 사용할 수 있음
// Custom Shader GUI
// Custom/Redify.shader
Shader "Custom/Redify" {
    Properties {
        _MainTex ("Base (RGB)", 2D) = "white" {}
    }
    SubShader {
        Tags { "RenderType"="Opaque" }
        LOD 200
         
        CGPROGRAM
        #pragma surface surf Lambert addshadow
        #pragma shader_feature REDIFY_ON
 
        sampler2D _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;
 
            #if REDIFY_ON
            o.Albedo.gb *= 0.5;
            #endif
        }
        ENDCG
    }
    CustomEditor "CustomShaderGUI"
}
 
// CustomShdaerGUI.cs
using UnityEngine;
using UnityEditor;
using System;
 
public class CustomShaderGUI : ShaderGUI
{
    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
        // render the default gui
        base.OnGUI(materialEditor, properties);
 
        Material targetMat = materialEditor.target as Material;
 
        // see if redify is set, and show a checkbox
        bool redify = Array.IndexOf(targetMat.shaderKeywords, "REDIFY_ON") != -1;
        EditorGUI.BeginChangeCheck();
        redify = EditorGUILayout.Toggle("Redify material", redify);
        if (EditorGUI.EndChangeCheck())
        {
            // enable or disable the keyword based on checkbox
            if (redify)
                targetMat.EnableKeyword("REDIFY_ON");
            else
                targetMat.DisableKeyword("REDIFY_ON");
        }
    }
}

Depth Textures의 사용(Using Depth Textures)

Depth Render Textures

  • 각 픽셀이 높은 정밀도의 “Depth”값을 가진 Render Textures을 만들 수 있습니다(RenderTextureFormat.Depth).
  • 주로 이펙트에 씬의 깊이 값이 필요한 경우 (예를 들어, 소프트 파티클 화면 공간 주변광 오클루전(Screen Space Ambient Occlusion), 투명도는 모든 씬의 깊이가 필요합니다) 사용 됩니다.
  • 깊이 텍스처의 픽셀 값은 선형이 아닌 분포를 나타내고, 0에서 1까지의 범위입니다.
  • 사용되는 깊이 버퍼에 따라, 일반적으로 정밀도는 24 비트 또는 16 비트입니다. 깊이 텍스처에서 읽을 때는 0에서 1의 범위의 고정밀 값이 리턴됩니다.
  • 만약 카메라로부터의 거리를 얻을 필요가 있거나 다른 형태로 선형 값을 얻을 필요가 있는 경우, 수동으로 계산해야 합니다.

Unity의 Depth는 다른 플랫폼에서 각각 다르게 구현됨

  • Direct3D 9 (Windows)에서 깊이 텍스처는 네이티브 깊이 버퍼 또는 싱글 채널 32 비트 부동 소수점 텍스처(“R32F” Direct3D 포맷)입니다.
    • Graphics card must support either native depth buffer (INTZ format) or floating point render textures in order for them to work.
    • When rendering into the depth texture, fragment program must output the value needed.
    • When reading from depth texture, red component of the color contains the high precision value.
  • OpenGL (Mac OS X)에서 깊이 텍스처는 기본 OpenGL 깊이 버퍼입니다. ARB_depth_texture를 참조하십시오).
    • Graphics card must support OpenGL 1.4 or ARB_depth_texture extension.
    • Depth texture corresponds to Z buffer contents that are rendered, it does not use the result from the fragment program.
  • OpenGL ES 2.0 (iOS/Android)은 위의 OpenGL과 매우 비슷합니다.
    • GPU must support GL_OES_depth_texture extension.
    • Direct3D 11 (Windows)은 OpenGL처럼 네이티브 깊이 텍스처에 대응하고 있습니다.

쉐이더에서의 헬퍼 매크로(Depth texture shader hepler macros)

  • 대부분의 경우 깊이 텍스처는 카메라에서 깊이를 렌더링하는 데 사용됩니다. UnityCG.cginc include file은 위의 케이스의 복잡성에 대응하기 위한 매크로를 포함하고 있습니다.
  • UNITY_TRANSFER_DEPTH(o): 이것은 정점 Eye Space Depth(시야 공간 깊이)를 계산하고 o (float2 이어야 합니다)에 출력합니다. 깊이 텍스처에 렌더링할 때 정점 프로그램에서 사용하십시오. 네이티브 깊이 텍스처의 플랫폼에서 Z 버퍼 값은 암시적으로 렌더링되기 때문에 이 매크로는 아무것도 하지 않습니다.
  • UNITY_OUTPUT_DEPTH(i): 이것은 정점 Eye Space Depth를 i (float2 이어야 합니다)에서 복원합니다. 깊이 텍스처에 대해 렌더링할 때 프래그먼트 프로그램에서 사용하십시오. 네이티브 깊이 텍스처가 있는 플랫폼에서 이 매크로는 Z 버퍼 값이 암묵적으로 렌더링되기 때문에 항상 0을 리턴합니다.
  • COMPUTE_EYEDEPTH(i): 이것은 정점 Eye Space Depth를 계산하고, o에 출력합니다. 정점 프로그램에서 깊이 텍스처에 렌더링하지 않을 때 사용합니다.
  • DECODE_EYEDEPTH(i): 깊이 텍스처 i에서 고정밀 값을 받고 해당 Eye Space Depth를 리턴합니다. 이 매크로는 Direct3D에서는 단순히 i*FarPlane를 리턴합니다. 네이티브 깊이 텍스처가 있는 플랫폼에서 이 매크로는, 카메라의 범위와 일치하도록 값을 선형화하고 확장합니다.
// Depth Texture
Shader "Render Depth" {
  SubShader {
    Tags { "RenderType"="Opaque" }
    Pass {
        Fog { Mode Off }
        CGPROGRAM
 
        #pragma vertex vert
        #pragma fragment frag
        #include "UnityCG.cginc"
 
        struct v2f {
          float4 pos : SV_POSITION;
          float2 depth : TEXCOORD0;
        };
 
        v2f vert (appdata_base v) {
          v2f o;
          o.pos = mul (UNITY_MATRIX_MVP, v.vertex);
          UNITY_TRANSFER_DEPTH(o.depth);
          return o;
        }
 
        half4 frag(v2f i) : SV_Target {
          UNITY_OUTPUT_DEPTH(i.depth);
        }
        ENDCG
    }
  }
}

카메라의 깊이 텍스처(Camera's Depth Texture)

  • Unity에서 카메라는 깊이 또는 깊이+법선 텍스처를 생성할 수 있습니다.
  • 이것은 최소한의 G-buffer(그래픽 버퍼) 텍스처에서 포스트 프로세싱 효과 또는 사용자 정의 라이팅 모델(예를 들어 라이트 Pre-Pass)을 사용할 수 있습니다.
  • 카메라는 실제로 Shader Replacement 기능을 사용하여 깊이 텍스처를 빌드하기 때문에, 다른 그래픽 버퍼 설정이 필요한 경우에는 스스로 이것을 할 수 있습니다.

플랫폼 별 렌더링 차이(Platform Specific Rendering Differences)

Render Texture 좌표

  • 수직 텍스처 좌표의 표현 방법은 Direct3D와 OpenGL 유사 플랫폼 간에 차이가 있습니다:
    • Direct3D와 Metal에서는 상단이 제로의 좌표 위치가 되며, 아래쪽으로 갈수록 증가합니다.
    • OpenGL과 OpenGL ES는 하단이 제로의 좌표 위치가 되며, 위쪽으로 갈수록 증가합니다.
  • 대부분의 경우에 영향은 없지만, Render Texture에 렌더링하는 경우, 영향이 있습니다. 이 경우 Unity는 Direct3D에서 렌더링 할 때 의도적으로 렌더링을 거꾸로 반전하기 때문에 플랫폼 사이의 규칙은 그대로 유지됩니다.

쉐이더 LOD(Shader Level of Detail)

  • Shader LOD는 LOD값이 정해진 임계 값 이하인 경우, 쉐이더 또는 서브 쉐이더를 사용하도록 지정하는 방법
  • 기본적으로 허용되는 LOD 레벨은 제한이 없으며, 사용자의 하드웨어에서 지원하는 모든 쉐이더를 사용할 수 있습니다.
  • 그러나 어떤 경우에는 비록 하드웨어가 지원하는 경우에도 쉐이더의 디테일을 떨어뜨리고 싶은 경우가 있습니다.
  • 예를 들어, 저렴한 그래픽 카드에서 모든 기능이 지원되지만, 속도가 너무 느린 경우가 있습니다. 그래서 parallax normal 매핑을 사용하고 싶지 않은 경우 들수 있습니다.
  • Shader LOD는 개별 쉐이더마다 설정(Shader.maximumLOD를 사용하여) 하거나 모든 쉐이더에서 전역으로 사용([Shader.globalMaximumLOD](../ScriptReference/Shader -globalMaximumLOD.html)를 사용하여)할 수 있습니다.
  • 사용자가 만든 사용자 지정 쉐이더에서는 LOD 명령을 사용하여 어떤 서브 쉐이더에서나 LOD 값을 설정할 수 있습니다.

Unity 내장 쉐이더의 LOD

  • VertexLit kind of shaders = 100
  • Decal, Reflective VertexLit = 150
  • Diffuse = 200
  • Diffuse Detail, Reflective Bumped Unlit, Reflective Bumped VertexLit = 250
  • Bumped, Specular = 300
  • Bumped Specular = 400
  • Parallax = 500
  • Parallax Specular = 600

Debugging DirectX 11 shaders with Visual Studio

Implementing Fixed Function TexGen in Shaders

Clone this wiki locally