Skip to content

netpyoung/vs.shader-developing-using-unity

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

53 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

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 ๋”๋ธ”ํด๋ฆญ

About

๐Ÿ“š๐ŸŒ” ๋™์˜์ƒ๊ฐ•์ขŒ. https://shaderdev.com/

Topics

Resources

Stars

Watchers

Forks