Skip to content

Latest commit

ย 

History

History
1964 lines (1478 loc) ยท 54.4 KB

File metadata and controls

1964 lines (1478 loc) ยท 54.4 KB

ShaderDev

Study log on Chayan Vinayak Goswami's ShaderDev

00

01. What is Shader

์‰์ด๋”๋ž€ ํ™”๋ฉด์— ์ถœ๋ ฅํ•  ํ”ฝ์…€์˜ ์œ„์น˜์™€ ์ƒ‰์ƒ์„ ๊ณ„์‚ฐํ•˜๋Š” ํ•จ์ˆ˜
์‰์ด๋”(shader)๋ž€ '์ƒ‰์˜ ๋†๋‹ด, ์ƒ‰์กฐ, ๋ช…์•” ํšจ๊ณผ๋ฅผ ์ฃผ๋‹ค.'๋ผ๋Š” ๋œป์„ ๊ฐ€์ง„ shade๋ž€ ๋™์‚ฌ์™€ ํ–‰๋™์˜ ์ฃผ์ฒด๋ฅผ ๋‚˜ํƒ€๋‚ด๋Š” ์ ‘๋ฏธ์‚ฌ '-er'์„ ํ˜ผํ•ฉํ•œ ๋‹จ์–ด์ž…๋‹ˆ๋‹ค.
์ฆ‰, ์ƒ‰์˜ ๋†๋‹ด, ์ƒ‰์กฐ, ๋ช…์•” ๋“ฑ์˜ ํšจ๊ณผ๋ฅผ ์ฃผ๋Š” ์ฃผ์ฒด๊ฐ€ ์‰์ด๋”๋ž€ ๋œป

- https://kblog.popekim.com/2011/11/01-part-1.html
์ฝ”์–ด๊ฐฏ์ˆ˜ ์—ฐ์‚ฐ
CPU ๋ช‡๊ฐœ serial operation
GPU ์ˆ˜์ฒœ๊ฐœ parallel operation
๊ฐ•๋ ฅํ•œ ๋งˆ์ดํฌ๋กœ ํ”„๋กœ์„ธ์„œ๋ฅผ ๋ช‡๊ฐœ ๋˜๋Š” ํฐ ํŒŒ์ดํ”„๋ฅผ ์“ฐ๋Š” ๋Œ€์‹ ,
๋งค์šฐ ์ž‘์€ ๋งˆ์ดํฌ๋กœ ํ”„๋กœ์„ธ์„œ๋“ค์„ ํ•œ๋ฒˆ์— ๋Œ๋ฆฌ๋Š” ๊ฒƒ์ด๋‹ค. ๊ทธ๊ฒƒ์ด ๋ฐ”๋กœ GPU(Graphic Processor Unit).

- https://thebookofshaders.com/01/?lan=kr
์‰์ด๋” ๊ธฐ๋Šฅ
Vertex
Geometry input primitive
Fragment / Pixel
Compute ๋ Œ๋”๋ง ํŒŒ์ดํ”„๋ผ์ธ์— ์†ํ•ด ์žˆ์ง€ ์•Š์Œ. GPU ๋ณ‘๋ ฌ ์ฒ˜๋ฆฌ ๋ชฉ์ 
Tessellation / Hull OpenGL 4, DirectX3D 11, Metal

02. Working of a Shader

ํŒŒ์ดํ”„๋ผ์ธ

vulkan_simplified_pipeline

Vertex Shader Input/Output

  • Vertex Shader Input
    • Position(Local/Object Space)
    • Normal
    • Color
    • ...
  • Vertex Shader Output
    • Position(Clip Space)
    • other infos

Rasterize

  1. geometry์— ์–ด๋–ค Sample๋“ค์ด ํ™”๋ฉด์— ๊ทธ๋ ค์ง€๋Š”์ง€ ๊ฒฐ์ •ํ•˜๊ณ (sampling)
  2. Vertex-Output์„ ์ด์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ(Fragment)๋“ค์„ interpolateํ•˜์—ฌ Fragment Shader๋กœ ๋„˜๊น€.

Fragment Shader

Fragment๋ฅผ ์ด์šฉํ•˜์—ฌ, ๊ฐ ํ”ฝ์…€์˜ ๊ฐ’(์ƒ‰)์„ ๊ตฌํ•œ๋‹ค.

03. Components of a Shader

Shader "ShaderName"
{
  Properties
  {
  }

  Sub-Shader
  {
    Tags
    {
    }

    Pass
    {
      hardware features(support graphics api(metal / gles / xbox360))
      [#pragma onlyrenderer metal]
      occlusion pass
      lighting pass
      beauty(diffuse, color) pass

      Vertext-Shader-Input
      Fragment-Shader-Input

      Vertex-Shader
      Fragment-Shader
    }
  }
  Fallback
}

04. Bare-bones shader

Shader "ShaderDevURP/BareBone"
{
    Properties
    {
        _Color("Main Color", Color) = (1, 1, 1, 1)
    }

        SubShader
    {
        Tags
        {
            "RenderType" = "Opaque"
            "RenderPipeline" = "UniversalPipeline"
        }

        Pass
        {
            HLSLPROGRAM
            #pragma vertex vert
            #pragma fragment frag

            #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"

            CBUFFER_START(UnityPerMaterial)
                half4 _Color;
            CBUFFER_END

            struct Attributes
            {
                float4 positionOS   : POSITION;
            };

            struct Varyings
            {
                float4 positionHCS  : SV_POSITION;
            };

            Varyings vert(Attributes IN)
            {
                Varyings OUT = (Varyings)0;
                OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
                return OUT;
            }

            half4 frag() : SV_Target
            {
                return _Color;
            }
            ENDHLSL
        }
    }
}

05. Model-View-Projection Matrix

MVP model_to_world_to_camera model_to_world_to_camera_to_homogeneous

coordinate_systems

Coordinate System ์ขŒํ‘œ๊ณ„ ์ขŒํ‘œ๋ฅผ ์ด์šฉํ•˜์—ฌ, ํŠน์ • ์š”์†Œ์˜ ์œ„์น˜๋ฅผ ์ •์˜.
Coordinate Space ์ขŒํ‘œ๊ณต๊ฐ„ ํ•œ์ ์˜ ์œ„์น˜๊ฐ€ ๋‹ค๋ฅธ ์ ๊ณผ์˜ ๊ด€๊ณ„๋กœ ๊ทœ์ •.
  • Vector4 ์ด์œ 

    (x, y, z, w)
    w == 1 (x,y,z,1) position in space
    w == 0 (x,y,z,0) direction
  • Matrix 4x4 ์ด์œ 

    ์„ ํ˜•๋ณ€ํ™˜์œผ๋กœ ํ™•๋Œ€/์ถ•์†Œ, ํšŒ์ „, ์ฐŒ๊ทธ๋Ÿฌ๋œจ๋ฆฌ๊ธฐ(skewing)์˜ ์กฐํ•ฉ์„ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๋ฐฐ์› ์ฃ .
    ์„ ํ˜•๋ณ€ํ™˜๋งŒ์œผ๋กœ๋Š” ํ‰ํ–‰์ด๋™์„ ๋งŒ๋“ค์–ด๋‚ผ ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์ด ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค
    ...
    ์„ ํ˜•๋ณ€ํ™˜์— ์ƒ์ˆ˜ํ•ญ์ด ์ฒจ๊ฐ€๋œ ๋ณ€ํ™˜์„ affine ๋ณ€ํ™˜์ด๋ผ๊ณ 
    ...
    
    - https://gpgstudy.com/forum/viewtopic.php?t=25011
    
  • ์˜ˆ) ์ด๋™ ๋งคํŠธ๋ฆญ์Šค x ๋ฐฉํ–ฅ๋ฒกํ„ฐ

    translationExampleDirection1

  • ์˜ˆ) ์ด๋™ ๋งคํŠธ๋ฆญ์Šค x ์œ„์น˜๋ฐฑํ„ฐ

    translationExamplePosition1

06. Depth Sorting / Z-Sorting

  • Z-Sorting -> Render Queue -> Painter's algorithm(์นด๋ฉ”๋ผ์™€ ๊ฑฐ๋ฆฌ ๊ธฐ๋ฐ˜)

  • Render Queue

    Tags { "Queue" = "Geometry-1" }
    
min default max
0 100 1499 Background
1500 2000 2399 Geometry
2400 2450 2699 AlphaTest
2700 3000 3599 Transparent
3600 4000 5000 Overlay
0 Rendered First Back
5000 Rendered Last Front

07. Sub Shader Tags

  • Tags๋Š” ,๋กœ ๊ตฌ๋ถ„ํ•˜์ง€ ์•Š๋Š”๋‹ค.(๊ณต๋ฐฑ์œผ๋กœ ๊ตฌ๋ถ„.)

    Tags { ___ = ___   ___ = ___ }

TODO: IgnoreProjector

"IgnoreProjector" = "True" "IgnoreProjector" = "False"

RenderType

08. Blending

Blend(srcFactor, blendOp, dstFactor)

srcFactor: ์ž‘์—… ๋Œ€์ƒ [0 ~ 1]
dstFactor: ์ปฌ๋Ÿฌ๋ฒ„ํผ์— ์žˆ๋Š” ๊ฐ’๋“ค [0 ~ 1]
blendOp: Add(default), Sub, RevSub, Min, Max ...

Merged Pixel = blendOp((srcColor * srcFactor), (dstColor * dstFactor))

unity_blend.png

blending1

blending2

09. Texture Mapping

// Texture ์†์„ฑ
// Wrap Mode - Clamp / Repeat

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

uniform sampler2D _MainTex;
uniform float4 _MainTex_ST;

float4 texcoord : TEXCOORD0;

_MainTex_ST.xy; // Tiling
_MainTex_ST.zw; // Offset

float4 color = tex2D(_MainTex, texcoord);


// UnityCG.cginc
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) (tex.xy * name##_ST.xy + name##_ST.zw)

out.texcoord.xy = in.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
out.texcoord.xy = TRANSFORM_TEX(in.texcoord, _MainTex);
Blend SrcAlpha OneMinusSrcAlpha

TEXTURE2D(_MainTex); SAMPLER(sampler_MainTex);
            
CBUFFER_START(UnityPerMaterial)
    float4 _MainTex_ST;
CBUFFER_END

struct Attributes
{
    float4 uv           : TEXCOORD0;
};

struct Varyings
{
    float4 uv           : TEXCOORD0;
};

Varyings vert(Attributes IN)
{
    OUT.uv = TRANSFORM_TEX(IN.uv, _MainTex);
}

half4 frag() : SV_Target
{
    float4 tex = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, IN.uv);
}

// com.unity.render-pipelines.core/ShaderLibrary/API/D3D11.hlsl
#define TEXTURE2D(textureName)                Texture2D textureName
#define SAMPLER(samplerName)                  SamplerState samplerName
#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2)                               textureName.Sample(samplerName, coord2)

// com.unity.render-pipelines.core/ShaderLibrary/Macros.hlsl
#define TRANSFORM_TEX(tex, name) ((tex.xy) * name##_ST.xy + name##_ST.zw)

10. Gradient Pattern

Direct X

    UV ์ขŒํ‘œ๊ณ„๊ฐ€ ํ…์Šค์ฒ˜ ๋ฉ”๋ชจ๋ฆฌ ๋ ˆ์ด์•„์›ƒ๊ณผ ์ผ์น˜ํ•œ๋‹ค๋Š” ์žฅ์ 
    ๋”ฐ๋ผ์„œ UV์ขŒํ‘œ๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ…์Šค์ฒ˜ ์กฐ์ž‘(texture manipulation)์„ ํ•˜๋ฉด ๋งค์šฐ ์ง๊ด€์ ์ด๊ณ  ์‰ฌ์›€
    - https://blog.popekim.com/ko/2012/06/11/unity-i-love-you-but-your-uv-is-horrible.html

(0,0)        (1,0)
  +-----+-----+
  |     |     |
  |     |     |
  +-----+-----+
  |     |     |
  |     |     |
  +-----+-----+
(0,1)        (1,1)


OpenGL / UnityEngine

(0,1)        (1,1)
  +-----+-----+
  |     |     |
  |     |     |
  +-----+-----+
  |     |     |
  |     |     |
  +-----+-----+
(0,0)        (1,0)

Quad, Plane์˜ UV๋งตํ•‘์ด ๋‹ค๋ฅด๋‹ค. Quad๋Š” ์ขŒํ•˜๋‹จ. Plane์€ ์šฐํ•˜๋‹จ

๊ทธ๋ž˜ํ”„์ƒ์„ฑ ์œ ํ‹ธ

11. Wave Functions

  • sqrt / sin / cos / tan ๊ทธ๋ž˜ํ”„

12. Line Pattern

half DrawLine(half2 uv, half start, half end)
{
    if (start < uv.x && uv.x < end)
    {
        return 1;
    }
    return 0;
}

13. Union and Intersection

14. Circle Pattern

half DrawCircle(half2 uv, half2 cp, half r)
{
    // cp : center position
    // r  : radius

    half x2y2 = pow((uv.x - cp.x), 2) + pow((uv.y - cp.y), 2);
    half r2 = pow(r, 2);
    if (x2y2 > r2)
    {
        return 0;
    }
    return 1;
}

15. Smoothstep

float smoothstep(float a, float b, float x)
{
    float t = saturate((x - a)/(b - a));
    return t * t * (3.0 - (2.0 * t));
}
smoothstep(1, 0.5, uv.x);

+----------+----------+----------+----------+
1(from)    0.75       0.5(to)    0.25       0
from to
1 0.5 texcoord.x return
1 0.5 0 1
1 0.5 0.25 1
1 0.5 0.5 1
1 0.5 0.75 0.5
1 0.5 1 0

16. Circle Fading Edges

float drawCircleFade(float2 uv, float2 cp, float r, float feather)
{
    float x2y2 = pow((uv.x - cp.x), 2) + pow((uv.y - cp.y), 2);
    float r2 = pow(r, 2);
    if (x2y2 > r2)
    {
        return 0;
    }
    return smoothstep(r2, r2 - feather, x2y2);
}

17. Pattern Animation

sin / cos ํ•จ์ˆ˜์™€ _Time๋ณ€์ˆ˜๋ฅผ ์ด์šฉํ•œ ์—๋‹ˆ์—๋ฏธ์…˜.

Name Type Value
_Time float4 Time since level load (t/20, t, t * 2, t * 3), use to animate things inside the shaders.
_SinTime float4 Sine of time: (t/8, t/4, t/2, t).
_CosTime float4 Cosine of time: (t/8, t/4, t/2, t).
unity_DeltaTime float4 Delta time: (dt, 1/dt, smoothDt, 1/smoothDt).

18. Vertex Animation

  • ๊นƒ๋ฐœ์˜ vertex position์„ sin์œผ๋กœ ํ”๋“ค๊ณ  ์ค‘์‹ฌ์  ์œ„์น˜ ๋ณด์ •.
half3 VertexFlagAnim(half3 positionOS, half2 uv)
{
    positionOS.z += sin((uv.x - (_Time.y * _FlagSpeed)) * _FlagFrequency) * (uv.x * _FlagAmplitude);
    return positionOS;
}

19. Normals

  • vertex normal
  • face normal

๊ตฌํ•˜๊ณ ์ž ํ•˜๋Š” vertex๋ฅผ ํฌํ•จํ•˜๊ณ  ์žˆ๋Š” face normal์„ ๋ชจ๋‘ ๊ตฌํ•˜๊ณ  normalize๋ฅผ ํ•˜๋ฉด vertex normal์„ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.

20. Normal-Vertex Animation

half3 VertexAnimNormal(half3 positionOS, half3 normalOS, half2 uv)
{
    positionOS += sin((normalOS - (_Time.y * _Speed)) * _Frequency) * (normalOS * _Amplitude);
    return positionOS;
}

21. Rendering Pipeline - part 1

rendering_pipeline

RenderState

  • Material
  • Vertex shader
  • Pixel shader
  • texture
  • Lighting setting

Batch

RenderState์˜ ๋ณ€ํ™”.

์˜ˆ)

[RenderStateX [Draw A] [Draw B] [Draw C]]

DrawCall          : 3๋ฒˆ (A, B, C)
RenderState       : RenderStateX
Batches           : 1๋ฒˆ (A, B, C๊ฐ€ ๋™์ผํ•œ RenderState)
Saved by batching : 2.  (A๋‹ค์Œ์— ์˜ค๋Š” B, C๋ฅผ ๊ทธ๋ฆด ๋™์•ˆ RenderState๋ณ€ํ™”๊ฐ€ ์—†์Œ.)

Fragment Shader ์ดํ›„

ZTest
  -> Pass <Z-Buffer>
  -> ๋ธ”๋žœ๋”ฉ
  -> [์„ ํƒ์ ]์Šคํ…์‹ค ํ…Œ์ŠคํŠธ
  -> Pass
  -> [์„ ํƒ์ ] Color Mask
  -> Final Color
  -> <Color Buffer>

22. Rendering Pipeline - part 2

ZWrite [On]/Off Z-Buffer ๊ฐ’์„ ์ž‘์„ฑํ• ์ง€ ์•ˆํ• ์ง€. Off์‹œ Z-Buffer ๋ณ€๊ฒฝ์•ˆํ•จ. On์‹œ ZTestํ†ต๊ณผ์‹œ Z-Buffer๊ฐ’์„ ํ˜„์žฌ ZTest๊ฐ’์œผ๋กœ ์„ค์ •(๋ถˆํˆฌ๋ช… ์˜ค๋ธŒ์ ํŠธ์—์„œ ๋งŽ์ด ์“ฐ์ž„)
Cull [Back] / Front / Off ํ•ด๋‹น ๋ฉด์„ ๋ Œ๋”๋ง ํ•˜์ง€ ์•Š์Œ
ZTest [(<=)LEqual]/Less/NotEqual/Always ... if ( Z-Buffer xop Z-Depth ) { Zwrite }

z_buffer_and_color_buffer.jpg

23. Normal Maps Types

Object-Space Normal Map

  • forward/backward face๊ธฐ๋ฐ˜(+z, -z).
  • Normal์˜ xyz๋ฅผ rgb๋กœ Texture์— ์ €์žฅ.
  • ๋”ฐ๋ผ์„œ x, y, z๊ฐ€ 0~1์‚ฌ์ด์˜ ๋ชจ๋“  ๋ฐฉํ–ฅ์œผ๋กœ ์ ์ ˆํ•˜๊ฒŒ ๋ถ„๋ฐฐ๋˜์–ด ์•Œ๋ก๋‹ฌ๋กํ•˜๊ฒŒ ๋ณด์ž„.

Tangent-Space Normal Map

  • forward face๊ธฐ๋ฐ˜.
  • Tangent Vector๋Š” Normal Vector์™€ ์ˆ˜์ง์ธ ๋ฒกํ„ฐ์ด๋‹ค(์—ฌ๋Ÿฌ๊ฐœ...). ๋”ฐ๋ผ์„œ ํ†ต์ƒ์ ์œผ๋กœ UV ์ขŒํ‘œ์™€ ๋น„๊ตํ•˜์—ฌ
    • Tangent Vector: U ์ขŒํ‘œ์™€ ์ผ์น˜ํ•˜๋Š” Vector
    • BiTangent Vector: V ์ขŒํ‘œ์™€ ์ผ์น˜ํ•˜๋Š” Vector

TBN-matrix

TBN = | Tx Ty Tz | // Tangent  | U
      | Bx By Bz | // Binormal | V
      | Nx Ny Nz | // Normal
Software Red Green Blue
Unity X+ Y+ Z+
Maya X+ Y+ Z+
Blender X+ Y+ Z+
Unreal X+ Y- Z+
3ds Max X+ Y- Z+
  • Right handedness, which coincides with OpenGL is indicated with a plus sign (ex. +Y)
  • Left handedness, which coincides with DirectX, is indicated with a negative sign (ex. -Y)

24. Points and Vectors

25. Vector Multiplication

  • ๋‚ด์ ๊ณผ ์™ธ์  ๊ณต์‹.
  • ๋‚ด์ ๊ณผ ์™ธ์ ์„ ์‹œ๊ฐ์ ์œผ๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•จ.
  • ์ด๊ฑฐ ์ด๋ฆ„ ํ–‡๊ฐˆ๋ฆฌ๊ธฐ ์‰ฌ์›€.

| Dot Product | Inner Product | ๋‚ด์  |

  • ๋‹ท์€ ์ ์ด๋‹ˆ๊นŒ ๋ชจ์ด๋Š”๊ฑด ๋‚ด์ 
  • ์ ์ด๋‹ˆ๊นŒ ๋‘๊ฐœ ๋ชจ์•„์„œ ํ•˜๋‚˜๊ฐ€ ๋จ.
  • ํ•˜๋‚˜๋กœ ๋ชจ์ด๋‹ˆ ๋‘ ๋ฒกํ„ฐ ์‚ฌ์ด์˜ ๊ฐ๋„๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ์Œ.
  • ๊ฐ๋„๋‹ˆ๊นŒ cos์—ฐ์‚ฐ ๋“ค์–ด๊ฐ.
  • https://rfriend.tistory.com/145
  • ๊ตํ™˜๋ฒ•์น™์ด ์„ฑ๋ฆฝ
| ๊ฐ๋„ | ๊ฐ’  |
| ---- | --- |
| 0    | 1   |
| 90   | 0   |
| 180  | -1  |
| -270 | 0   |

        1
        |
        |
0-------+------ 0
        |
        |
       -1

| Cross Product | Outer Product | ์™ธ์  |

  • ํฌ๋กœ์Šค๋Š” ์‚์ฃฝํ•˜๋‹ˆ๊นŒ ์™ธ์ ์œผ๋กœ ์™ธ์šธ๊ป.
  • X ๋‹ˆ๊นŒ ์‚์ €๋‚˜์˜ด.
  • X๊ฐ€ ์ง๊ฐ์ด๋‹ˆ ์ˆ˜์ง ๊ตฌํ• ๋•Œ ์”€.
  • https://rfriend.tistory.com/146
  • ๊ตํ™˜๋ฒ•์น™ ์„ฑ๋ฆฝ์•ˆํ•จ

26. Normal Map Shader - intro

TBN : (Tangent Binormal Normal)

obj TBN ๊ธฐ๋ฐ˜์œผ๋กœ world_N ๊ตฌํ•˜๊ธฐ

VS
    obj_TBN = float3(Input.T, cross(Input.N, Input.T), Input.N); // object to tangent TBN

PS
      obj_N = mul(inverse(obj_TBN), tangent_N);
            = mul(transpose(obj_TBN), tangent_N);
            = mul(tangent_N,  obj_TBN);
    world_N = mul(obj_N, unity_World2Object);

world TBN ๊ธฐ๋ฐ˜์œผ๋กœ world_N ๊ตฌํ•˜๊ธฐ

world TBN๊ธฐ๋ฐ˜์œผ๋กœ world Normal์„ ์–ป๊ธฐ์œ„ํ•ด PS์—์„œ ํ•œ๋ฒˆ๋งŒ ๊ณฑํ•˜๋ฉด ๋œ๋‹ค.

VS
      world_T =    mul(unity_Object2World, Input.T);            // ํ‘œ๋ฉด์— ๋ถ™์–ด์žˆ์œผ๋ฏ€๋กœ shifting๊ณผ ๋ฌด๊ด€
      world_N =    mul(Input.N           , unity_World2Object); // shifting ๋ฐฉ์ง€.
      world_B =  cross(world_N, world_T);
    world_TBN = float3(world_T, world_B, world_N); // world to tangent TBN.

PS
    world_N = mul(tangent_N, world_TBN);

normal shiting

figure10.8

     M == unity_Object2World;
M_want == transpose( inverse(unity_Object2World) )
       == transpose( unity_World2Object )

mul(matrix, vector) == mul(vector, transpose(matrix))

mul(M_want, v) == mul( transpose( unity_World2Object ), V )
               == mul(                               V, unity_World2Object )
inline void ExtractTBN(in half3 normalOS, in float4 tangent, inout half3 T, inout half3  B, inout half3 N)
{
    N = TransformObjectToWorldNormal(normalOS);
    T = TransformObjectToWorldDir(tangent.xyz);
    B = cross(N, T) * tangent.w * unity_WorldTransformParams.w;
}

inline half3 CombineTBN(in half3 tangentNormal, in half3 T, in half3  B, in half3 N)
{
    return mul(tangentNormal, float3x3(normalize(T), normalize(B), normalize(N)));
}
float3x3 tangentToWorld = CreateTangentToWorld(unnormalizedNormalWS, tangentWS.xyz, tangentWS.w > 0.0 ? 1.0 : -1.0);

// com.unity.render-pipelines.core/ShaderLibrary/SpaceTransforms.hlsl
real3x3 CreateTangentToWorld(real3 normal, real3 tangent, real flipSign)
{
    // For odd-negative scale transforms we need to flip the sign
    real sgn = flipSign * GetOddNegativeScale();
    real3 bitangent = cross(normal, tangent) * sgn;

    return real3x3(tangent, bitangent, normal);
}

float3 TransformObjectToWorldNormal(float3 normalOS, bool doNormalize = true)
{
#ifdef UNITY_ASSUME_UNIFORM_SCALING
    return TransformObjectToWorldDir(normalOS, doNormalize);
#else
    // Normal need to be multiply by inverse transpose
    float3 normalWS = mul(normalOS, (float3x3)GetWorldToObjectMatrix());
    if (doNormalize)
        return SafeNormalize(normalWS);

    return normalWS;
#endif
}

float3 TransformObjectToWorldDir(float3 dirOS, bool doNormalize = true)
{
    #ifndef SHADER_STAGE_RAY_TRACING
    float3 dirWS = mul((float3x3)GetObjectToWorldMatrix(), dirOS);
    #else
    float3 dirWS = mul((float3x3)ObjectToWorld3x4(), dirOS);
    #endif
    if (doNormalize)
        return SafeNormalize(dirWS);

    return dirWS;
}

normal-1

normal-2

1

2

3

from tangent_N to world_N

  • ์œ ๋‹ˆํ‹ฐ์˜ rgb ์ž…๋ ฅ ๋ฒ”์œ„๋Š” [0 ~ 1]
  • ์œ ๋‹ˆํ‹ฐ์˜ ๋…ธ๋ฉ€์˜ ๋ฒ”์œ„๋Š” [-1 ~ 1]
  • n๋”ฐ๋ผ์„œ rgb์—์„œ ๋…ธ๋ฉ€์˜ ๊ตฌํ• ๋ ค๋ฉด ๋ฒ”์œ„๋ฅผ 2๋ฐฐ๋กœ ๋Š˜๋ฆฌ๊ณ , -1๋งŒํผ ์ด๋™์‹œ์ผœ์ค˜์•ผํ•จ.
  • (color channel * 2) - 1
PS
    tangent_N = tex2D(_N_Texture, Input.mUV).rgb;
    tangent_N = (tangent_N * 2) - 1;
      world_N = mul(tangent_N, world_TBN);

27. DXT-Compression

  • S3 Texture Compression
  • DXT Compression
  • 4x4 ํ”ฝ์…€ ์ค‘์—, ์ƒ‰ 2๊ฐœ๋ฅผ ๊ณ ๋ฆ„. 2๊ฐœ์˜ ์ƒ‰์„ interpolation์‹œ์ผœ์„œ 4x4 color ์ธ๋ฑ์Šค๋ฅผ ๋งŒ๋“ฌ.
  • ์†์‹ค์••์ถ•.

DXT1 ํฌ๋งท์„ ์ด์šฉ

V color channel bit
X R color0 16
Y G color1 16
Z B x 0
XYZ๊ฐ€ normalize ๋˜์—ˆ๋‹ค๋ฉด, X์™€ Y๋งŒ ์•Œ์•„๋„ Z๋ฅผ ๊ตฌํ•  ์ˆ˜ ์žˆ๋‹ค.

1 = (X * X) + (Y * Y) + (Z * Z)
Z = sqrt(1 - ((X * X) + (Y * Y)))
// com.unity.render-pipelines.core/ShaderLibrary/Packing.hlsl

real3 UnpackNormal(real4 packedNormal)
{
#if defined(UNITY_ASTC_NORMALMAP_ENCODING)
    return UnpackNormalAG(packedNormal, 1.0);
#elif defined(UNITY_NO_DXT5nm)
    return UnpackNormalRGBNoScale(packedNormal);
#else
    // Compiler will optimize the scale away
    return UnpackNormalmapRGorAG(packedNormal, 1.0);
#endif
}

// Unpack normal as DXT5nm (1, y, 0, x) or BC5 (x, y, 0, 1)
real3 UnpackNormalmapRGorAG(real4 packedNormal, real scale = 1.0)
{
    // Convert to (?, y, 0, x)
    packedNormal.a *= packedNormal.r;
    return UnpackNormalAG(packedNormal, scale);
}

real3 UnpackNormalAG(real4 packedNormal, real scale = 1.0)
{
    real3 normal;
    normal.xy = packedNormal.ag * 2.0 - 1.0;
    normal.z = max(1.0e-16, sqrt(1.0 - saturate(dot(normal.xy, normal.xy))));
    normal.xy *= scale;
    return normal;
}

28. Normal Map Shader - part 1

29. Normal Map Shader - part 2

    uniform sampler2D _MainTex;
    uniform float4 _MainTex_ST;

PS
    Output.T = normalize(mul(Input.T, unity_ObjectToWorld));
    Output.N = normalize(mul(Input.N, unity_WorldToObject));
    Output.B = normalize(cross(Output.N, Output.T) * Input.T.w);

VS
    // ์ผ๋ฐ˜ ํƒ„์  ํŠธ๋งต ๋ฒ„์ „.
    float3 colorT = tex2D(_Tangent_Map, Input.mUV).rgb;
    float3 tangent_N = colorT * 2 - 1;

    // DXT5nm ๋ฒ„์ „.
    float3 colorT = tex2D(_Tangent_Map_DXT5nm, Input.mUV).rgb;
    float3 tangent_N   = float(colorT.a * 2 - 1, colorT.g * 2 - 1, 0);
           tangent_N.z = sqrt(1 - dot(tangent_N.xy, tangent_N.xy));

    float3x3 world_TBN = float3x3(Input.T, Input.B, Input.N); // world to tangent TBN
    float3   world_N   = mul(inverse(world_TBN), tangent_N);
                       = mul(transpose(world_TBN), tangent_N);
                       = mul(tangent_N, world_TBN);

Input.T.w๋ฅผ ๊ณฑํ•˜๋Š” ์ด์œ 

  • UV, ST ๋„๋Œ€์ฒด ๋ญ์•ผ.
    • 3d ์ขŒํ‘œ๊ณ„์—์„œ xyzw ์ทจํ•จ. uv๋‚จ์Œ. st๋‚จ์Œ.
    • uv - ํ…์Šค์ฒ˜ ์ขŒํ‘œ๊ณ„
    • st - ํ…์…€(texel = Texture + pixel) ์ขŒํ‘œ๊ณ„
UV - texture's coordinate
       +-------+ (1, 1)
       |       |
       |       |
(0, 0) +-------+

ST - surface's coordinate space.
       +-------+ (32, 32)
       |       |
       |       |
(0, 0) +-------+

    o.texcoord.xy = (v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw)

| xy  | tiling |
| zw  | offset |

30. Outline Shader - intro

ํ–‰๋ ฌ

๋‹จ์œ„ ํ–‰๋ ฌ

| 1 0 0 0 |
| 0 1 0 0 |
| 0 0 1 0 |
| 0 0 0 1 |

์ด๋™(translate) ํ–‰๋ ฌ

| 1 0 0 x |
| 0 1 0 y |
| 0 0 1 z |
| 0 0 0 1 |

์Šค์ผ€์ผ(scale) ํ–‰๋ ฌ

| x 0 0 0 |
| 0 y 0 0 |
| 0 0 z 0 |
| 0 0 0 1 |

ํšŒ์ „ ํ–‰๋ ฌ

2์ฐจ์› ํšŒ์ „

| x' | = | cos$ -sin$||x|
| y' |   | sin$  cos$||y|

3์ฐจ์› ํšŒ์ „

  • ํšŒ์ „ํ–‰๋ ฌ ๊ธฐ์ค€์œผ๋กœ ์ƒ๊ฐํ•œ๋‹ค.
  • 2์ฐจ์› ํšŒ์ „ ํ–‰๋ ฌ์„ ๊ธฐ์–ตํ•œ๋‹ค.
  • ๊ธฐ์ค€ ํ–‰ ์•„๋ž˜๊ฐ€ -sin$์ด๋‹ค.
X

| 1(x)  0    0     0    | (x ์•„๋ ˆ -sin$)
| 0     cos$ -sin$ 0    |
| 0     sin$  cos$ 0    |
| 0     0    0     1    |

Y

| cos$  0    sin$  0    |
| 0     1(y) 0     0    | (y ์•„๋ ˆ -sin$)
| -sin$ 0    cos$  0    |
| 0     0    0     1    |

Z

| cos$  -sin$ 0    0    |
| sin$   cos$ 0    0    |
| 0     0     1(z) 0    | (z์˜ ์•„๋ž˜ ๋งˆ์ง€๋ง‰ ์—ด์€ ๋น„์›Œ์•ผํ•˜๋‹ˆ ๋งจ ์œ„๊ฐ€ -sin$)
| 0     0     0    1    |

์•„์›ƒ๋ผ์ธ ์‰์ด๋” ๊ฐœ๊ด„

  • Pass 1
    • ๊ธฐ์ค€ ๋ชจ๋ธ ์Šค์ผ€์ผ ์—….
    • outline ์ƒ์ƒ์œผ๋กœ ์น ํ•˜๊ธฐ
  • Pass 2
    • ๊ทธ ์œ„์— ๋ง ๊ทธ๋ฆฌ๊ธฐ

31. Outline Shader - code

  • normal ์‚ฌ์ถœ๋ฐฉ์‹.
    • ๋‹จ์ , ๋ฉด๋“ค ์‚ฌ์ด์˜ ๊ฐญ๋“ค์ด ๋ณด์ž„.
  • ๋งคํŠธ๋ฆญ์Šค๋ฅผ ํ†ตํ•œ vertex ํ™•๋Œ€.
Zwrite Off
Cull Front

half4 Outline(half4 vertexPosition, half w)
{
    half4x4 m;
    m[0][0] = 1.0 + w; m[0][1] = 0.0;     m[0][2] = 0.0;     m[0][3] = 0.0;
    m[1][0] = 0.0;     m[1][1] = 1.0 + w; m[1][2] = 0.0;     m[1][3] = 0.0;
    m[2][0] = 0.0;     m[2][1] = 0.0;     m[2][2] = 1.0 + w; m[2][3] = 0.0;
    m[3][0] = 0.0;     m[3][1] = 0.0;     m[3][2] = 0.0;     m[3][3] = 1.0;
    return mul(m, vertexPosition);
}
// 1. HLSL ๋ฐฉ๋ฒ•.
// ref: https://blog.naver.com/mnpshino/222058677191
// UniversalRenderPipelineAsset_Renderer
// - Add Feature> Render Objects
//   - Add Pass Names (same as LightMode)

// 2. ShaderGraph๋ฐฉ๋ฒ•.
// ref: https://walll4542.wixsite.com/watchthis/post/unityshader-14-urp-shader-graph
// - Graph Inspector
//   - Alpha Clip ์ฒดํฌ
//   - Two Sided ์ฒดํฌ
//   - Is Front Face> Branch> Fragment's Alpha๋กœ ์•ŒํŒŒ์ ์šฉ.

32. Author_s Check-in

33. Multi Variant Shader and Cginc files

[KeywordEnum(On, Off)] _UseNormal("_UserNormalMap, float) = 0

[Enum(On 1, Off)]

[Toggle]
[KeywordEnum(On, Off)] _UseNormal("_UserNormalMap, float) = 0
;; => _USE_NORMAL_ON // _USE_NORMAL_OFF

#pragma multi_compile _USE_NORMAL_ON
#pragma shader_feature _USE_NORMAL_ON

#if _USE_NORMAL_ON
#endif
  • ์—ฌ๋Ÿฌ multi_compile ๊ฒฐํ•ฉ

    • ์—ฌ๋Ÿฌ๊ฐœ์˜ multi_compile์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ๊ณ , ์ƒ์„ฑ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ์กฐํ•ฉ์— ๋Œ€ํ•ด ์ปดํŒŒ์ผ๋จ.

      #pragma multi_compile A B C
      #pragma multi_compile D E
    • ์ฒซ ๋ฒˆ์งธ ์ค„์—์„œ ์„ธ ๊ฐ€์ง€ ๋ฐฐ๋ฆฌ์–ธํŠธ๊ฐ€ ์ƒ์„ฑ๋˜๊ณ , ๋‘ ๋ฒˆ์งธ ์ค„์—์„œ ๋‘ ๊ฐ€์ง€ ๋ฐฐ๋ฆฌ์–ธํŠธ๊ฐ€ ์ƒ์„ฑ๋˜์–ด, ์ด ์—ฌ์„ฏ๊ฐœ(3 * 2)์˜ ์…ฐ์ด๋” ๋ฐฐ๋ฆฌ์–ธํŠธ(A+D, B+D, C+D, A+E, B+E, C+E)๊ฐ€ ์ƒ์„ฑ๋จ

  • Difference between shader_feature and multi_compile

    shader_feature is very similar to multi_compile.
    The only difference is that Unity does not include unused variants of shader_feature shaders in the final build.
    For this reason, you should use shader_feature for keywords that are set from the Materials, while multi_compile is better for keywords that are set from code globally.

34. Multi Variant Shader - part 1

[KeywordEnum(On, Off)] _UseNormal("_UserNormalMap, float) = 0

#pragma shader_feature _USE_NORMAL_ON

#if _USE_NORMAL_ON
#else
#endif

35. Multi Variant Shader - part 2

float3 normalFromColor (float4 colorVal)
{
    #if defined(UNITY_NO_DXT5nm)
        return colorVal.xyz * 2 - 1;
    #else
        // R => x => A
        // G => y
        // B => z => ignored

        float3 normalVal;
        normalVal = float3 (
            colorVal.a * 2.0 - 1.0,
            colorVal.g * 2.0 - 1.0,
            0.0
        );
        normalVal.z = sqrt(1.0 - dot(normalVal, normalVal));
        return normalVal;
    #endif
}

float3 WorldNormalFromNormalMap(sampler2D normalMap, float2 normalTexCoord, float3 tangentWorld, float3 binormalWorld, float3 normalWorld)
{
    // Color at Pixel which we read from Tangent space normal map
    float4 colorAtPixel = tex2D(normalMap, normalTexCoord);

    // Normal value converted from Color value
    float3 normalAtPixel = normalFromColor(colorAtPixel);

    // Compose TBN matrix
    float3x3 TBNWorld = float3x3(tangentWorld, binormalWorld, normalWorld);
    return normalize(mul(normalAtPixel, TBNWorld));
}

36. Basic Lighting Model and Rendering Path - part 1

36. Basic Lighting Model and Rendering Path - part 2

BEADS(๊ตฌ์Šฌ ๋ชฉ๊ฑธ์ด)

  • Basic Lighting Model
Ambient ์ฃผ๋ณ€๊ด‘ ์ „์ฒด์ 
Diffuse ๋‚œ๋ฐ˜์‚ฌ๊ด‘ ํŠน์ •๋ฐฉํ–ฅ ์ž…์‚ฌ, ๊ณ ๋ฅด๊ฒŒ ๋ฐ˜์‚ฌ
Specular ์ „๋ฐ˜์‚ฌ๊ด‘ ํŠน์ •๋ฐฉํ–ฅ ์ž…์‚ฌ, ํŠน์ •๋ฐฉํ–ฅ์œผ๋กœ ์ •ํ™•ํžˆ ๋ฐ˜์‚ฌ
Emisive ๋ฐœ์‚ฐ ๋ฐœ๊ด‘์ฒด

Fowrad Rendering

  • https://docs.unity3d.com/Manual/RenderTech-ForwardRendering.html
  • 5 object x 4 lighting = 20 draw call
  • ์ตœ์ ํ™” ํ•ด์„œ ๋ผ์ดํŠธ๊ฐ€ ์˜ํ–ฅ์„ ์ฃผ๋Š” ์˜ค๋ธŒ์ ํŠธ๋งŒ ๊ทธ๋ฆผ
  • ์–ด์จ‹๋“ , ๋ผ์ดํŠธ๊ฐ€ ๋Š˜์–ด๋‚  ์ˆ˜๋ก, ๋“œ๋กœ์šฐ ์ฝœ ์ˆ˜๊ฐ€ ๋ฐฐ๋กœ ๋Š˜์–ด๋‚จ.
  • ๋ชจ๋ฐ”์ผ๊ฐ™์€ ์ฒ™๋ฐ•ํ•œ ํ™˜๊ฒฝ์—์„œ๋Š”
    • ๋ผ์ดํŠธ๋ฅผ ํ•˜๋‚˜๋งŒ ์œ ์ง€
    • ๋ผ์ดํŠธ๋ฅผ ๋ฏธ๋ฆฌ ํ…์Šค์ณ์— ๊ตฌ์Œ.

Base Pass

Tag { Queue = Transparency ...}
Pass {
    LightMode = "Forward Base"
}
  • 1 per pixel directional light rendering
    • Spherical harmonic lights(Light probes, Global Illumination, Sky Ambient)

Additional Pass

Pass {
    LightMode = "Forward Add"
}
  • 1 per pixel additional light
directional ๋ผ์ดํŠธ๋ž‘ point ๋ผ์ดํŠธ๊ฐ€ ์žˆ์œผ๋ฉด,
directional light์—๋Š” forward base๋กœ
point light์—๋Š” forward add๋กœ ๋‘๊ฐ€์ง€ ํŒจ์Šค๋ฅผ ์ž‘์„ฑํ•ด์•ผ ํ•œ๋‹ค.

Legacy Deferred Lighting

  1. ์”ฌ์„ Geometry Buffer์— ๋ Œ๋”๋งํ•œ๋‹ค.(๋ณด์—ฌ์ง€๋Š” ๊ฐ ํ”ฝ์…€์˜ depth, normal, specular power)
  2. Light Accumulation
    • ๊ฐ ๋ผ์ดํŠธ์— ์˜ํ–ฅ์„ ๋ฐ›๋Š” ํ”ฝ์…€์„ ์ฐพ์Œ.
    • ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ ๋ฒ„ํผ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์Œ
    • ๋ผ์ดํŠธ ๊ฐ’์„ ๊ณ„์‚ฐ
    • Light Accumulation buffer์— ์ €์žฅ.
  3. ์”ฌ์„ ๋‹ค์‹œ ๋ Œ๋”๋ง ํ•œ๋‹ค.
    • Accumulated light value + Mesh color + Ambient or Emissive light

Deferred Shading

  1. ์”ฌ์„ Geometry Buffer(g-buffer)์— ๋ Œ๋”๋งํ•œ๋‹ค.
    • depth
    • diffuse color
    • normal(world space)
    • specular color
    • smoothness
    • emission
  2. Light Accumulation
    • ๊ฐ ๋ผ์ดํŠธ์— ์˜ํ–ฅ์„ ๋ฐ›๋Š” ํ”ฝ์…€์„ ์ฐพ์Œ.
    • ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ ๋ฒ„ํผ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ฝ์Œ
    • ๋ผ์ดํŠธ ๊ฐ’์„ ๊ณ„์‚ฐ
    • Light Accumulation buffer์— ์ €์žฅ.
    • accumulated-light value์™€ diffuse color + spec + emission๋ฅผ ํ•ฉ์นœ๋‹ค.
  • deferred shading vs deferred lighting
    • deferred shading์—์„œ๋Š” ์”ฌ์„ ๋‹ค์‹œ ๋ Œ๋”๋ง ํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค.(์ด๋ฏธ ์ง€์˜ค๋ฉ”ํŠธ๋ฆฌ ๋ฒ„ํผ์— ์ €์žฅํ–ˆ๊ธฐ๋•Œ๋ฌธ์—)
  • Unity requirement for deferred shading
    • Graphic Card with multiple render target
    • Support Shader Model 3 or later
    • Support for Depth-Render Texture

38. Diffuse Reflection - intro

  • ์š”ํ•œ ํ•˜์ธ๋ฆฌํžˆ ๋žจ๋ฒ„ํŠธ (Johann Heinrich Lambert)
  • ๋žจ๋ฒ„ํŠธ์˜ ๋ฒ•์น™์„ ๋งŒ์กฑํ•˜๋Š” ํ‘œ๋ฉด์„ ๋žจ๋ฒ„์‹œ์•ˆ (Lambertian)์ด๋ผ ํ•จ.
  • ๋žจ๋ฒ„ํŠธ ์ฝ”์‚ฌ์ธ ๋ฒ•์น™(lambert's cosine law)
    • light in reflected off a surface based on cosine-fall off.
  • Fowrad Rendering ๊ธฐ๋ฐ˜์œผ๋กœ
    • ์”ฌ์— ํ•˜๋‚˜ ์ด์ƒ์˜ ๋ผ์ดํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด, ํ•˜๋‚˜์˜ ๊ฐ€์žฅ ๋ฐ์€ directional light๊ฐ€ Base Pass์— ์‚ฌ์šฉ.
    • ๋‹ค๋ฅธ ๋ผ์ดํŠธ๋“ค์€ Spherical Harmonics๋กœ ๊ฐ„์ฃผ.
๋ฒกํ„ฐ L์™€ N์˜ ์‚ฌ์ด๊ฐ์„ x๋ผ ํ–ˆ์„๋•Œ, ๋‚ด์ ๊ฐ’์€(๋‚ด์ ์€ ๊ตํ™˜๋ฒ•์น™ ์„ฑ๋ฆฝ)

dot(L, N) = |L| * |N| * cos(x)

L, N์ด ๋‹จ์œ„๋ฐฑํ„ฐ์ผ๋•Œ |L|, |N|๋Š” 1.

cos(x) = dot(L, N)

๋”ฐ๋ผ์„œ lambert ๊ฐ’์€

lambert = cos(x)
        = dot(L, N)

VS์—์„œ lambert๊ฐ’์„ ๊ตฌํ•˜๋ฉด ๋ณด๊ฐ„๊ฐ’์„ ์ด์šฉํ•˜๊ธฐ์—, PS์—์„œ lambert๊ตฌํ•œ ๊ฒƒ๊ณผ์˜ ์ฐจ์ด๊ฐ€ ์žˆ๋‹ค.

39. Diffuse Reflection - code 1

40. Diffuse Reflection - code 2

41. Diffuse Reflection - code 3

42. Specular Reflection - intro

specular_reflection.jpg

์ž…์‚ฌ๋ฒกํ„ฐ(incident)๋ฅผ I๋ผ ํ–ˆ์„๋•Œ reflect(I, N)์€

R = reflect(I, N)
  = I - 2 * N * dot(I, N)

43. Specular Reflection - code 1

44. Specular Reflection - code 2

N: Normal
L: Light
R: Reflect
V: Viewport
H: Halfway( normalize(L + V) )

L  N  R
 \ | /
  \|/
---+---
    \
     \
     -L

      Phong Reflection Model : max(0, dot(R, N))^S
Blinn-Phong Reflection Model : max(0, dot(H, N))^S
// tex2D - pixel shader only
// float4 specularMap = tex2D(_SpecularMap, o.texcoord.xy);

// tex2Dlod - 2D texture lookup with specified level of detail and optional texel offset.
// samp : Sampler to lookup.
// s.xy : Coordinates to perform the lookup.
// s.w : Level of detail. (0 ~ n-1) (๊ฐ€์žฅํฐ)์ฒซ๋ฒˆ์งธ ๋ฐ‰๋งต์ด 0

#pragma target 3.0
float4 specularMap = tex2Dlod(_SpecularMap, o.texcoord);

#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod)                      textureName.SampleLevel(samplerName, coord2, lod)
half specularColor = SAMPLE_TEXTURE2D_LOD(_SpecularMap, sampler_SpecularMap, OUT.uv, 0).r;

45. Ambient Reflection - intro

Windows> Ligiting> Environment> Environment Lighting> Source> Color
Windows> Ligiting> Environment> Environment Lighting> Ambient Color> ์ง€์ •.

์ฃผ๋ณ€(Ambient) ๋ฐ˜์‚ฌ๊ด‘.

 A = ambient property of material * global ambient
   =                           KA * UNITY_LIGHTMODEL_AMBIENT
// ref: [Get Ambient Color in custom shader](https://forum.unity.com/threads/get-ambient-color-in-custom-shader.994786/)
// half3 ambientColor = _AmbientFactor * UNITY_LIGHTMODEL_AMBIENT;
half3 ambientColor = _AmbientFactor * half3(unity_SHAr.w, unity_SHAg.w, unity_SHAb.w);

// ref: com.unity.render-pipelines.universal/ShaderLibrary/ShaderGraphFunctions.hlsl
// #define SHADERGRAPH_AMBIENT_SKY unity_AmbientSky
half3 ambientColor = _AmbientFactor * unity_AmbientSky;
unity_AmbientSky fixed4 Sky ambient lighting color in gradient ambient lighting case.
unity_AmbientEquator fixed4 Equator ambient lighting color in gradient ambient lighting case.
unity_AmbientGround fixed4 Ground ambient lighting color in gradient ambient lighting case.
UNITY_LIGHTMODEL_AMBIENT fixed4 Ambient lighting color (sky color in gradient ambient case). Legacy variable.

46. Ambient Reflection - code.mkv

47. Wrap up Basic Lighting Model

48. Advanced Lighting Model

๊ธฐ๋ณธ ๋ผ์ดํŠธ ๋ชจ๋ธ์—๋Š” ๋ญ”๊ฐ€ ์ข€ ๋ถ€์กฑํ•˜๋‹ค.

  • ๊ทธ๋ฆผ์ž(Shadow)
  • ์˜ค๋ธŒ์ ํŠธ๊ฐ„ ์ƒํ˜ธ์ž‘์šฉ(Inter Object interaction)
  • ์—๋„ˆ์ง€ ๊ท ํ˜•(Energy Balance)
    • Energy balanced shading model

49. Hemispherical Lighting Model

  • ์˜ค๋ธŒ์ ํŠธ๋Š” ๊ตฌ์˜ ์„ผํ„ฐ์— ๋น›์˜ ๋ฐฉํ–ฅ์ด ๊ตฌ์˜ ๋ฐ”๊นฅ์—์„œ ์•ˆ์ชฝ์œผ๋กœ ๋น„์ถ˜๋‹ค ๊ฐ€์ •.
  • Hemispherical(๋ฐ˜๊ตฌํ˜•) Lighting Model
    • 2 half sphere
upper sky N.L > 0
lower ground N.L <= 0

hemispherical

50. Image Based Lighting

๋งŽ์€ ๋ผ์ดํŠธ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ณ„์‚ฐํ•˜๊ธฐ์—๋Š” ๋ฌด๋ฆฌ

  • light์ •๋ณด๋ฅผ ํ…์Šค์ณ์— ์ €์žฅ
    • Chrome ball
      • ๋ˆˆ์— ๊ฐ€๊ธ‰์  ๋งŽ์€ ๊ตฌ์—ญ์„ ๋‹ด์„ ์ˆ˜ ์žˆ๋„๋ก ์นด๋ฉ”๋ผ๋ฅผ ๋ฉ€๋ฆฌ ๋ฐฐ์น˜
      • ๋งต์— ํฌ๋กฌ๋ณผ(chrome ball)์„ ๋ฐฐ์น˜(๋ˆˆ์— ๋ณด์ด๋Š” ๋ฐฉํ–ฅ์œผ๋กœ๋ถ€ํ„ฐ ๋ชจ๋“  ๋ผ์ดํŠธ ์ •๋ณด๋ฅผ ์ €์žฅ)(์ด๋Ÿฌํ•œ ํฌ๋กฌ๋ณผ์„ light probe๋ผ ํ•œ๋‹ค)
    • Fish eye lens
      • 185๋„๊นŒ์ง€ ์บก์ณ ๊ฐ€๋Šฅํ•œ ๋ Œ์ฆˆ๊ฐ€ ์žˆ์Œ.
      • 2๊ฐœ๋กœ ๋ฌถ์–ด 360๋„๋ฅผ ์บก์ณ. ํ™˜๊ฒฝ๋งต์„ ๋งŒ๋“ฌ.
  • light probe๋กœ๋ถ€ํ„ฐ ํ™˜๊ฒฝ๋งต(sphere, cube)์„ ์ œ์ž‘
  • ํ™˜๊ฒฝ ๋งต์œผ๋กœ๋ถ€ํ„ฐ light๊ณ„์‚ฐ

51. Irradiance Environment Map

  • ๋ณต์‚ฌ์กฐ๋„ ํ™˜๊ฒฝ๋งต
  • Irradiance : ๋ฌด์–ธ๊ฐ€๋กœ๋ถ€ํ„ฐ ๋‚˜์˜ค๋Š” ๋น›์˜ ์–‘์„ ๋‚˜ํƒ€๋‚ด๋Š” ๋‹จ์œ„
  • IBL(Image Based Rendering) : ํ™˜๊ฒฝ๋งต์ด ์ˆ˜๋ฐ˜๋˜๋Š” ํ…Œํฌ๋‹‰
texCube - ์–ด๋–ค ํ…์…€์ด ๋…ธ๋ฉ€ ๋ฐฉํ–ฅ๊ณผ ๋งŒ๋‚˜๊ฒŒ ๋˜๋Š”๊ฐ€.

color = texCube(_Cube_Texture, NormalDirection);

Light Environment Ma

  • ๋น›์˜ ์ •๋ณด(์œ„์น˜, ๋ฐ๊ธฐ๋“ฑ)์„ ํ…์…€์— ์ €์žฅ

1. Light Map

์˜ค๋ธŒ์ ํŠธ๋“ค์˜ ์ด๋ฏธ์ง€๋ฅผ ์ €์žฅ.

  • ์”ฌ์˜ ๋ชจ๋“  ๋ฏธ๋ฆฌ ๊ณ„์‚ฐ๋œ ๋น›์˜ ์ •๋ณด๋ฅผ ํ…์Šค์ณ์— ์ €์žฅ.
  • ์˜ค๋ธŒ์ ํŠธ์˜ N๊ณผ ๋น›์˜ L์— ๊ธฐ๋ฐ˜ํ•˜์—ฌ, ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•˜์—ฌ ์ €์žฅํ•˜์˜€๊ธฐ์— ๋‚˜์ค‘์— ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ํšŒ์ „ํ•˜๊ฑฐ๋‚˜ ๋ณ€ํ•˜๊ฒŒ๋˜๋ฉด ๋ฏธ๋ฆฌ ๊ณ„์‚ฐํ•œ ๊ฐ’๊ณผ ๋งž์ง€ ์•Š๊ฒŒ๋œ๋‹ค.

2. Irradiance Environment Map

์›”๋“œ์„ผํ„ฐ์˜ ๊ตฌ์˜ N๊ณผ ํ™˜๊ฒฝ๋งต์˜ L์— ๋Œ€ํ•œ diffuse๊ฐ’(dot(N, L))์„ ์ €์žฅ.

  • ํ™˜๊ฒฝ๋งต(light)์˜ ๋ชจ๋“  ํ…์…€์ด, ์›”๋“œ์„ผํ„ฐ์— ๊ตฌ๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •.
  • ๊ตฌ์˜ N๊ณผ ํ…์…€์˜ L์— ๋Œ€ํ•ด dot(N, L)์„ ๊ตฌํ•˜๊ณ .
  • ๊ทธ์— ๋Œ€ํ•œ ์ƒ‰๊น”์„ Irradiance Environment Map์˜ ํ…์…€์— ์ €์žฅ.

Irradiance Map๋งŒ๋“ค๊ธฐ.

  • Irradiance Map์˜ ๊ฐ ํ…์…€๋งˆ๋‹ค
    • ์„ผํ„ฐ๋กœ๋ถ€ํ„ฐ ํ…์…€๋กœ์˜ ๋ฐฉํ–ฅ(Normal๊ฐ’)์„ ๊ตฌํ•˜๊ณ 
    • Lighting Environment map์˜ ๊ฐ ํ…์…€๋งˆ๋‹ค
      • ๋ฏธ๋ฆฌ ์กฐ๋ช…์ฒ˜๋ฆฌ๋œ diffuse๊ฐ’์„ ๊ฐ€์‚ฐํ•˜๊ณ 
    • ๊ณ„์‚ฐ๋œ diffuse ๊ฐ’์„ Irradiance Map์˜ ํ…์…€์— ์ €์žฅํ•œ๋‹ค.
foreach (irr_texel in irradiance_map.texels)
{
    N = calculateDirectionFromCenter(irr_texel);
    diffuseColor = 0
    foreach (light_texel in lighting_environment_map.texels)
    {
        L = calculateDirectionFromCenter(light_texel)
        diffuseColor += Vector.Dot(N, L)
    }
    irr_texel.color = diffuseColor;
}
return irradiance_map

52. Image Based Reflection - intro

cubemaps_reflection.png

๊ตฌํ˜• ๋ฐ˜์‚ฌ์ฒด๋ฅผ ํ๋ธŒ๋งต ์•ˆ์— ์œ„์น˜์‹œํ‚ค๊ณ , ๋ฐ˜์‚ฌ์ฒด์—์„œ ๋ฐ˜์‚ฌ๋˜์–ด ํ๋ธŒ๋งต์— ๋ง๋‹ฟ์€ ์ •๋ณด๋ฅผ ์ €์žฅํ•œ๋‹ค.

V : ์›”๋“œ ๋ทฐ ๋ฐฉํ–ฅ N : ์›”๋“œ ์˜ค๋ธŒ์ ํŠธ์˜ ํ‘œ๋ฉด Normal VR : ์›”๋“œ ๋ทฐ ๋ฐฉํ–ฅ์˜ ๋ฐ˜์‚ฌ ๋ฐฉํ–ฅ

texCUBElod  - LOD๋Š” (level of detail)๋ฅผ ์˜๋ฏธ.

texel = texCUBElod(cubeMap, VR.xyzw);

xyz : direction
w   : detail(max: 1)

53. Image Based Reflection - code 1

float3 IBL_Reflection(
    samplerCUBE cubeMap,
    half        detail,
    float3      reflect,
    float       exeposure,
    float       factor)
{
    float4 c = texCUBElod(cubeMap, float4(reflect, detail));
    return factor * c.rgb * (c.a * exeposure);
}
// com.unity.render-pipelines.core/ShaderLibrary/API/D3D11.hlsl
#define TEXTURECUBE_PARAM(textureName, samplerName)               TEXTURECUBE(textureName),       SAMPLER(samplerName)
#define SAMPLE_TEXTURECUBE(textureName, samplerName, coord3)                             textureName.Sample(samplerName, coord3)
#define SAMPLE_TEXTURECUBE_LOD(textureName, samplerName, coord3, lod)                    textureName.SampleLevel(samplerName, coord3, lod)

half3 IBL_Reflection(TEXTURECUBE_PARAM(cubeMap, sampler_cubeMap), half detail, half3 worldRefl, half exposure, half reflectionFactor)
{
    half4 cubeMapCol = SAMPLE_TEXTURECUBE_LOD(cubeMap, sampler_cubeMap, worldRefl, detail).rgba;
    return reflectionFactor * cubeMapCol.rgb * (cubeMapCol.a * exposure);
}

54. Image Based Reflection - code 2

55. Image Based Refraction - intro1

cubemaps_refraction.png

  • IBL-Refraction
    • IBL(Image Based Lighting)
    • Refraction: ๊ตด์ ˆ

56. Image Based Refraction - intro 2

์œ ๋ฆฌ๋‚˜ ๋ฌผ์€ ๋ฐ˜์‚ฌ์™€ ๊ตด์ ˆ ๋ชจ๋‘๋ฅผ ๊ฐ–๋Š”๋ฐ...

SnellsLaw.png

  • Snell's law ๊ณต์‹ ์œ ๋„ ์„ค๋ช….
  • Willebrord Snellius
  • nvidia: refract
float3 refract(float3 i, float3 n, float eta)
{
  float cosi = dot(-i, n);
  float cost2 = 1.0f - eta * eta * (1.0f - cosi * cosi);
  float3 t = eta * i + ((eta * cosi - sqrt(abs(cost2))) * n);
  return t * (float3)(cost2 > 0);
}

57. Image Based Refraction - code

// ๋งค์งˆ์— ๋Œ€ํ•œ ๋ฐ˜์‚ฌ
float3 world_reflect_V = reflect(-world_V, world_N);

// ๋งค์งˆ์— ๋Œ€ํ•œ ๊ตด์ ˆ
float3 world_refract_V = refract(-world_V, world_N, 1 / _RefractiveIndex);

58. Image Based Fresnel - intro

half3 V = normalize(GetWorldSpaceViewDir(IN.positionWS));

// dot(V, N)๋Š” ๊ฐ๋„๊ฐ€ ์ข์„์ˆ˜๋ก 1๋กœ ์ˆ˜๋ ดํ•˜๋‹ˆ,
// ๊ฐ๋„๊ฐ€ ์ปค์ง€๋ฉด ๋” ๋ฐ๋„๋ก One Minus.
half fresnelWeight = 1 - saturate(dot(V, N));

// ๊ฑฐ๋ฆฌ์— ๋”ฐ๋ฅธ ๋น„์œจ ๋ณด๊ฐ„.
half fresnel = smoothstep(1 - _FresnelWidth, 1, fresnelWeight);

half3 reflectVN = reflect(-V, N);
half3 reflectColor = IBL_Reflection(_CubeMap, sampler_CubeMap, _ReflectionDetail, reflectVN, _ReflectionExposure, _ReflectionFactor);

// fresnel๋กœ ๋ณด๊ฐ„ํšจ๊ณผ
finalColor.rgb = lerp(finalColor.rgb, finalColor.rgb * reflectColor, fresnel);

lerp

Blinn-phong ์˜ˆ

fres-01.png

fres-02.png

H    = normalize( V + L )
spec = pow(saturate(dot(H, N)), power);

Blinn-phong์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ทธ๋ฆผ์—์„œ Half-vector๋ฅผ ์ด์šฉํ•˜๊ธฐ์— ๋ฐ˜์‚ฌ๋˜๋Š” ํฌ๊ธฐ๊ฐ€ ๊ณ„์‚ฐ์ƒ ๊ฐ™๊ฒŒ ๋‚˜์˜ฌ๊ฒƒ์ด๋‹ค. ํ•˜์ง€๋งŒ, ํ˜„์‹ค์—์„œ๋Š” L๊ณผ V์˜ ๊ฐ๋„๊ฐ€ ์ปค์ง€๋ฉด ๋ฐ˜์‚ฌ๋˜์–ด ๋ฐ๊ฒŒ ๋น›๋‚˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ๋‹ค.

shot_01.jpg

Fresnel๋กœ ๋ฆผ๋ผ์ดํŠธํšจ๊ณผ์™€ ๋ฐ˜์‚ฌ๊ด‘ํšจ๊ณผ๋ฅผ ํ‰๋‚ด๋‚ผ ์ˆ˜์žˆ๋‹ค.

๊ตด์ ˆ๋ฅ ์ด n1์ธ ๋งค์งˆ์—์„œ n2์ธ ๋งค์งˆ๋กœ ๋น›์ด ํˆฌ๊ณผํ•  ๋•Œ ๋ฐ˜์‚ฌ์™€ ๊ตด์ ˆ์ด ์ผ์–ด๋‚œ๋‹ค. ํ”„๋ ˆ๋„ฌ ๋ฐฉ์ •์‹์€ ์ด ์„ฑ์งˆ์„ ๋ฐ˜์‚ฌ๊ณ„์ˆ˜, ํˆฌ๊ณผ๊ณ„์ˆ˜๋กœ ๋‚˜๋ˆ„์–ด ์„ฑ๋ถ„์„ ๋ถ„์„ํ•˜์—ฌ ํ‘œํ˜„ํ•œ ๋ฐฉ์ •์‹์ด๋‹ค

// H  is the standard half-angle vector.
// F0 is reflectance at normal incidence (for skin use 0.028).
float fresnelReflectance( float3 H, float3 V, float F0 )
{
  float base = 1.0 - dot( V, H );
  float exponential = pow( base, 5.0 );
  return exponential + F0 * ( 1.0 - exponential );
}

59. Image Based Fresnel - code 1

60. Image Based Fresnel - code 2

61. Coordinate Spaces

62. Transforming Coordinate Spaces

NDC(Normalized Device Coordinate) [-1, 1]
-1,  1                1,  1
  +--------------------+
  |                    |
  |                    |
  |       0,0          |
  |                    |
  |                    |
  +--------------------+
-1, -1                1, -1


Texture Coord [0, 1]
D3D
(0,0)        (1,0)
  +-----+-----+
  |     |     |
  |     |     |
  +-----+-----+
  |     |     |
  |     |     |
  +-----+-----+
(0,1)        (1,1)


OpenGL

(0,1)        (1,1)
  +-----+-----+
  |     |     |
  |     |     |
  +-----+-----+
  |     |     |
  |     |     |
  +-----+-----+
(0,0)        (1,0)

[-1, 1] => [0, 1] = (NDC + 1) / 2

NDC.x = proj_X / proj_W = x / w
U = (x / w + 1) * 0.5
  = (x + w) / w * 0.5
  = (1 / w) * (x + w)  * 0.5
V = (1 / w) * (y + w)  * 0.5
_ProjectionParams.x : -1 TopLeft    D3D
                       1 BottomLeft Opengl

UNITY_HALF_TEXEL_OFFSET์ธ ๊ฒฝ์šฐ _ScreenParams.zw๋ฅผ ๊ณฑํ•ด์ค€๋‹ค.
inline float4 ProjectionToTextureSpace(float4 pos)
{
    float4 textureSpacePos = pos;
    #if defined(UNITY_HALF_TEXEL_OFFSET)
        textureSpacePos.xy = float2 (textureSpacePos.x, textureSpacePos.y * _ProjectionParams.x) + textureSpacePos.w * _ScreenParams.zw;
    #else
        textureSpacePos.xy = float2 (textureSpacePos.x, textureSpacePos.y * _ProjectionParams.x) + textureSpacePos.w;
    #endif
    textureSpacePos.xy = float2 (textureSpacePos.x/textureSpacePos.w, textureSpacePos.y/textureSpacePos.w) * 0.5f;
    return textureSpacePos;
}

// https://github.com/Unity-Technologies/Graphics/pull/2529
// com.unity.render-pipelines.universal/ShaderLibrary/ShaderVariablesFunctions.deprecated.hlsl

// Deprecated: A confusingly named and duplicate function that scales clipspace to unity NDC range. (-w < x(-y) < w --> 0 < xy < w)
// Use GetVertexPositionInputs().positionNDC instead for vertex shader
// Or a similar function in Common.hlsl, ComputeNormalizedDeviceCoordinatesWithZ()
float4 ComputeScreenPos(float4 positionCS)
{
    float4 o = positionCS * 0.5f;
    o.xy = float2(o.x, o.y * _ProjectionParams.x) + o.w;
    o.zw = positionCS.zw;
    return o;
}

63. Shadow Mapping - intro

  1. Z-depth๊ตฌํ•˜๊ธฐ

    1. ์”ฌ ๋ Œ๋”๋ง

    2. Z-depth๋ฅผ ๊นŠ์ด๋ฒ„ํผ์— ์ €์žฅํ•œ๋‹ค(depth map)

      world > View[Light] > Proj[Light]
            Light's View Matrix > Light's Projection Matrix
      > transform NDC
      > transform texture Space
  2. ๊ทธ๋ฆผ์ž๊ทธ๋ฆฌ๊ธฐ

    1. ์”ฌ ๋ Œ๋”๋ง

    2. ๊นŠ์ด๋ฒ„ํผ๋ž‘ Z-depth ํ…Œ์ŠคํŠธ

      if (fragment Z-depth > sampled Z-depth)
      {
          shadow : 0
      }
      else
      {
          lit     : 1
      }
// Built-in(legacy)
Tag {"LightMode" = "ShadowCaster"} => _ShadowMapTexture

TODO ๋”ฐ๋กœ ์ •๋ฆฌํ•œ ํŽ˜์ด์ง€๋กœ ๋งํฌ.

- Mesh Renderer> Lighting> Cast Shadow> On
- ShadowCaster Pass
- frag ํ•จ์ˆ˜์—์„œ shadow(0) / lit(1) ๋ฐ˜ํ™˜

world > View[Camera] > Proj[Camera]
            Camera's View Matrix > Camera's Projection Matrix
      > transform texture Space

64. Shadow Mapping - code

// builtin(legacy)
inline float4 ProjectionToTextureSpace(float4 positionHCS)
{
  float4 textureSpacePos = positionHCS;
  #if defined(UNITY_HALF_TEXEL_OFFSET)
    textureSpacePos.xy = float2 (textureSpacePos.x, textureSpacePos.y * _ProjectionParams.x) + textureSpacePos.w * _ScreenParams.zw;
  #else
    textureSpacePos.xy = float2 (textureSpacePos.x, textureSpacePos.y * _ProjectionParams.x) + textureSpacePos.w;
  #endif
  textureSpacePos.xy = float2 (textureSpacePos.x/textureSpacePos.w, textureSpacePos.y/textureSpacePos.w) * 0.5f;
  return textureSpacePos;
}

half4 shadowCoord = ProjectionToTextureSpace(positionHCS)
half shadowAttenuation = tex2D(_ShadowMapTexture, shadowCoord).a;

Pass
{
  Name "ShadowCaster"
  Tags { "Queue" = "Opaque" "LightMode" = "ShadowCaster" }
  ZWrite On
  Cull Off

  CGPROGRAM
  #pragma vertex vert
  #pragma fragment frag
  
  struct vertexInput
  {
    float4 vertex : POSITION;
  };
  struct vertexOutput
  {
    float4 pos : SV_POSITION;
  };
  
  vertexOutput vert (vertexInput v)
  {
    vertexOutput o;
    o.pos = UnityObjectToClipPos(v.vertex);
    return o;
  }
  
  float4 frag(vertexOutput i) : SV_Target
  {
    return 0;
  }
  ENDCG

}
  • Builtin(Legacy)์—์„œ๋Š” _ShadowMapTexture๋ฅผ ํ™œ์šฉํ•˜๋‚˜, URP์—์„œ๋Š” API๋„ ๋ฐ”๋€Œ๊ณ  ๋‚ด๋ถ€์ ์œผ๋กœ _MainLightShadowmapTexture๋ฅผ ํ™œ์šฉํ•˜๋„๋ก ๋ฐ”๋€Œ์—ˆ๋‹ค.
  • com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl
half4 shadowCoord = TransformWorldToShadowCoord(IN.positionWS);
ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
half4 shadowParams = GetMainLightShadowParams();
half shadowAttenuation = SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowCoord, shadowSamplingData, shadowParams, false);
finalColor.rgb *= shadowAttenuation;
// URP
half4 shadowCoord = TransformWorldToShadowCoord(positionWS);
// or
// VertexPositionInputs vertexInput = GetVertexPositionInputs(IN.positionOS.xyz);
// half4 shadowCoord = GetShadowCoord(vertexInput);

half shadowAttenuation = MainLightRealtimeShadow(shadowCoord);
// or
// ShadowSamplingData shadowSamplingData = GetMainLightShadowSamplingData();
// half4 shadowParams = GetMainLightShadowParams();
// half shadowAttenuation = SampleShadowmap(TEXTURE2D_ARGS(_MainLightShadowmapTexture, sampler_MainLightShadowmapTexture), shadowCoord, shadowSamplingData, shadowParams, false);
// or
// Light mainLight = GetMainLight(i.shadowCoord);
// half shadowAttenuation = mainLight.shadowAttenuation;

Pass
{
    Name "ShadowCaster"
    Tags
    {
        "LightMode" = "ShadowCaster"
    }

    ZWrite On
    Cull Back

    HLSLPROGRAM
    #pragma target 3.5

    #pragma vertex shadowVert
    #pragma fragment shadowFrag

    #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"  // real
    #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/CommonMaterial.hlsl" // LerpWhiteTo
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
    #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Shadows.hlsl" // ApplyShadowBias

    struct Attributes
    {
        float4 positionOS   : POSITION;
        float4 normal       : NORMAL;
    };

    struct Varyings
    {
        float4 positionHCS  : SV_POSITION;
    };

    Varyings shadowVert(Attributes IN)
    {
        Varyings OUT = (Varyings)0;

        float3 positionWS = TransformObjectToWorld(IN.positionOS.xyz);
        float3 normalWS = TransformObjectToWorldNormal(IN.normal.xyz);
        OUT.positionHCS = TransformWorldToHClip(ApplyShadowBias(positionWS, normalWS, _MainLightPosition.xyz));

        return OUT;
    }

    half4 shadowFrag(Varyings IN) : SV_Target
    {
        return 0;
    }
    ENDHLSL
}

65. Shadow Mapping - Glsl Compatible

// Legacy
#pragma multi_compile_fwdbase

#if _SHADOWMODE_ON
    #if defined(SHADER_API_D3D11) || defined(SHADER_API_D3D11_9X) || defined(UNITY_COMPILER_HLSLCC)
        Texture2D _ShadowMapTexture;
        SamplerComparisonState sampler_ShadowMapTexture;
    #elif defined(SHADER_TARGET_GLSL)
        sampler2DShadow _ShadowMapTexture;
    #else
        sampler2D _ShadowMapTexture;
    #endif
#endif

#if _SHADOWMODE_ON
    // ์—๋””ํ„ฐ๋Š” cascading shadows๋ฅผ ์‚ฌ์šฉ. ๋ชจ๋ฐ”์ผ ํ”Œ๋ ›ํผ์€ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Œ.
    #if defined(UNITY_NO_SCREENSPACE_SHADOWS)
        o.shadowCoord = mul(unity_WorldToShadow[0], o.posWorld);
    #else
        o.shadowCoord = ProjectionToTextureSpace(o.pos);
    #endif
#endif

#if _SHADOWMODE_ON
    #if defined(SHADER_TARGET_GLSL)
        float shadow =  shadow2D(_ShadowMapTexture, i.shadowCoord);
    #else
        // Factor in shadow strength using _LightShadowData.r
        #if defined(SHADER_API_D3D11) || defined(SHADER_API_D3D11_9X) || defined(UNITY_COMPILER_HLSLCC)
            float shadow = (_ShadowMapTexture.SampleCmpLevelZero (sampler_ShadowMapTexture, i.shadowCoord.xy, i.shadowCoord.z)? 1.0 : _LightShadowData.r);
        #elif defined(UNITY_NO_SCREENSPACE_SHADOWS)
            float shadow = ((tex2D(_ShadowMapTexture, i.shadowCoord.xy).r < i.shadowCoord.z) ? 1.0 : _LightShadowData.r);
        #else
            float shadow = tex2D(_ShadowMapTexture, i.shadowCoord).a;
        #endif
    #endif
#endif

66. BRDF - intro

BRDF ๋Š” "Bidirectional Reflectance Distribution Function" ์˜ ๋จธ๋ฆฌ๊ธ€์ž์ž…๋‹ˆ๋‹ค.
์šฐ๋ฆฌ ๋ง๋กœ๋Š” "์–‘๋ฐฉํ–ฅ ๋ฐ˜์‚ฌ์œจ ๋ถ„ํฌ ํ•จ์ˆ˜"์ž…๋‹ˆ๋‹ค.
์ด BRDF ๋Š” Diffuse BRDF ์™€ Specular BRDF ๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค.

์ถœ์ฒ˜: https://lifeisforu.tistory.com/386 [๊ทธ๋ƒฅ ๊ทธ๋Ÿฐ ๋ธ”๋กœ๊ทธ]

BRDF - ex) ๋ทฐ ๋ฐฉํ–ฅ๊ณผ ๋ผ์ดํŠธ ๋ฐฉํ–ฅ์œผ๋กœ๋ถ€ํ„ฐ, ๋ถˆํˆฌ๋ช…ํ•œ ํ‘œ๋ฉด์— ๋ฐ˜์‚ฌ๋˜๋Š” ๋ฐฉ์‹์„ ๊ตฌํ•จ.

ํŠน์ •๋ฐฉํ–ฅ(๋ˆˆ ํ˜น์€ ์นด๋ฉ”๋ผ              )์œผ๋กœ     ๋ฐ˜์‚ฌ๋œ ๋น›์˜ ์–‘
-------------------------------------------------------------
ํŠน์ •๋ฐฉํ–ฅ(ํŠน์ •ํฌ์ธํ„ฐ๋กœ๋ถ€ํ„ฐ์˜ ๋น›์˜ ๋ฐฉํ–ฅ)์œผ๋กœ๋ถ€ํ„ฐ ๋„๋‹ฌํ•œ ๋น›์˜ ์–‘
    Radiance
= -------------
    Irradiance


BRDF
    ๋ฐ˜์‚ฌ๋œ ๋น›์˜ ์–‘
= --------------------
    Li * ๋ฉด์  x Cos

  ๋“ฑ๋ฐฉ์„ฑ(  isotropic): ๋ฐ˜์‚ฌ๋„๊ฐ€ ํ‘œ๋ฉด์ด ํ–ฅํ•˜๋Š” ๋ฐฉํ–ฅ์ด๋‚˜ ํšŒ์ „์— ์˜ํ•ด ๋ณ€ํ•˜์ง€ ์•Š์Œ.
๋น„๋“ฑ๋ฐฉ์„ฑ(anisotropic): ๋ฐ˜์‚ฌ๋„๊ฐ€ ํ‘œ๋ฉด์ด ํ–ฅํ•˜๋Š” ๋ฐฉํ–ฅ์ด๋‚˜ ํšŒ์ „์— ์˜ํ•ด ๋ณ€ํ•จ.

Microfacet Theory

Radiance ๋ณต์‚ฌํœ˜๋„ ๋น›์˜ ํ‘œ๋ฉด์˜ ๋‹จ์œ„๋ฉด์ ๋‹น ๋ฐฉ์ถœ๋œ ์—๋„ˆ์ง€(๋‹จ์œ„ ์‹œ๊ฐ„๋‹น ํŠน์ • ๋ฐฉํ–ฅ)
Irradiance ๋ณต์‚ฌ์กฐ๋„ ๋ฐ›์€ ์—๋„ˆ์ง€(๋‹จ์œ„ ๋ฉด์ )

67. BRDF - Spherical Coordinate System

brdf

๊ตฌ๋ฉด์ขŒํ‘œ : $[r, \theta, \varphi]$

$\theta$ : z์ถ•์œผ๋กœ๋ถ€ํ„ฐ ๊ฐ๋„ $\varphi$: yxํ‰๋ฉด์œผ๋กœ ํˆฌ์˜๋œ ๋ฒกํ„ฐ๋กœ๋ถ€ํ„ฐ +x์ถ•์œผ๋กœ์˜ ๊ฐ๋„

์ƒ๋ฐ˜์„ฑ reciprocity

68. BRDF - Anisotropy - intro

  • Ashikhimin-Shirley && Ashikhimin-Premoze
    • Ashikhimin-Shirley ์ œ์•ˆ
    • Ashikhimin-Premoze์— ์˜ํ•ด ์ˆ˜์ •
H = Halfway
T = Tangent
B = Bitangent

${\sqrt{(n_u+1) + (n_v+1)} (N \cdotp H)^{ N_u(H \cdot T) + n_v(H \cdot B)^2 \over 1 -(N \cdot H)^2} \over 8_\pi \cdot (V \cdotp H) \cdot max((N \cdotp L), (N \cdotp V)) } \cdot FrennelTerm$

$F = (reflectionFactor + (1 - reflectionFactor) \cdot (1 - (V . H))^5)$

Ashikhimin_shirley_premoze

half AshikhminShirleyPremoze_BRDF(half nU, half nV, half reflectionFactor, half3 N, half3 T,  half3 L, half3 V);

69. BRDF - Anisotropy - code 1

70. BRDF - Anisotropy - code 2

float AshikhminShirleyPremoze_BRDF(float nU, float nV, float3 tangentDir, float3 normalDir, float3 lightDir, float3 viewDir, float reflectionFactor)
{
    float pi = 3.141592;
    float3 halfwayVector = normalize(lightDir + viewDir);
    float3 NdotH = dot(normalDir, halfwayVector);
    float3 NdotL = dot(normalDir, lightDir);
    float3 NdotV = dot(normalDir, viewDir);
    float3 HdotT = dot(halfwayVector, tangentDir);
    float3 HdotB = dot(halfwayVector, cross(tangentDir, normalDir));
    float3 VdotH = dot(viewDir, halfwayVector);

    float power = nU * pow(HdotT,2) + nV * pow(HdotB,2);
    power /= 1.0 - pow(NdotH,2);

    float spec = sqrt((nU + 1) * (nV + 1)) * pow(NdotH, power);
    spec /= 8.0 * pi * VdotH * max(NdotL, NdotV);

    float Fresnel = reflectionFactor + (1.0 - reflectionFactor) * pow(1.0 - VdotH, 5.0);
    spec *= Fresnel;
    return spec;
}

float4 tangentMap = tex2D(_TangentMap, o.texcoord.xy);
float3 specular = AshikhminShirleyPremoze_BRDF(_AnisoU, _AnisoV, tangentMap.xyz, o.normal, lightDir, worldViewDir, _ReflectionFactor);

71. Profiling Shaders using Xcode

  • Xcode ๋””๋ฒ„๊ทธ
    • ์นด๋ฉ”๋ผ๋ฒ„ํŠผ
    • RenderCommandEncoder ๋”๋ธ”ํด๋ฆญ