An open API service indexing awesome lists of open source software.

https://github.com/netpyoung/bs.physically_based_shader_develop_for_unity

:books:๐ŸŒ”์ฑ…๊ณต๋ถ€. ์œ ๋‹ˆํ‹ฐ ๋ฌผ๋ฆฌ ๊ธฐ๋ฐ˜ ์…ฐ์ด๋” ๊ฐœ๋ฐœ
https://github.com/netpyoung/bs.physically_based_shader_develop_for_unity

bs shader urp

Last synced: about 1 month ago
JSON representation

:books:๐ŸŒ”์ฑ…๊ณต๋ถ€. ์œ ๋‹ˆํ‹ฐ ๋ฌผ๋ฆฌ ๊ธฐ๋ฐ˜ ์…ฐ์ด๋” ๊ฐœ๋ฐœ

Awesome Lists containing this project

README

        

# ์œ ๋‹ˆํ‹ฐ ๋ฌผ๋ฆฌ ๊ธฐ๋ฐ˜ ์‰์ด๋” ๊ฐœ๋ฐœ

![./physically-based-shader-dev-for-unity-2017.jpg](./physically-based-shader-dev-for-unity-2017.jpg)

- [๋ฒˆ์—ญํŒ](http://www.acornpub.co.kr/book/physically-unity-shader)
- [source](https://github.com/Apress/physically-based-shader-dev-for-unity-2017)

Legacy(Built-in)์‰์ด๋”๋กœ ์ž‘์„ฑ๋˜์–ด์žˆ๋Š”๋ฐ, ์–ด์ฐจํ”ผ Legacy์‚ฌ์šฉ๋ฒ•๋„ ์ž˜ ๋ชจ๋ฅด๊ณ  URP๋กœ ๊ณง๋ฐ”๋กœ ์—ฐ์Šตํ•ด ๋ณด๋„๋ก ํ•˜์ž.

## URP (Universal Render Pipeline)

- [Dev Weeks: URP ๊ธฐ๋ณธ ๊ตฌ์„ฑ๊ณผ ํ๋ฆ„](https://www.youtube.com/watch?v=QRlz4-pAtpY)
- [Dev Weeks: URP ์…ฐ์ด๋” ๋œฏ์–ด๋ณด๊ธฐ](https://www.youtube.com/watch?v=9K1uOihvNyg)

``` tree
Packages/
|-- Core RP Library/
| |-- ShaderLibrary/
| | |-- SpaceTransform.hlsl - ๊ณต๊ฐ„๋ณ€ํ™˜ ํ–‰๋ ฌ. Tangent<->Worldํ–‰๋ ฌ
| | |-- Common.hlsl - ๊ฐ์ข… ์ˆ˜ํ•™. ํ…์Šค์ณ ์œ ํ‹ธ, ๋ށ์Šค ๊ณ„์‚ฐ ..
| | |-- >>> EntityLighting.hlsl - SH, ProveVolume, Lightmap๊ณ„์‚ฐ ???
| | |-- ImageBasedLighting - IBL๊ด€๋ จ ๋ถ€๋ถ„(GGX, Anisotropy, ImportanceSample)
|-- Universal RP/
| |-- ShaderLibrary/
| | |-- Core.hlsl - ๋ฒ„ํ…์Šค ์ธํ’‹ ๊ตฌ์กฐ์ฒด, ์Šคํฌ๋ฆฐUV๊ณ„์‚ฐ,Fog๊ณ„์‚ฐ
| | |-- Lighting.hlsl - ๋ผ์ดํŠธ ๊ตฌ์กฐ์ฒด, diffuse, specular, GI
| | |-- Shadows.hlsl - ์‰๋„์šฐ๋งต ์ƒ˜ํ”Œ๋ง, ์บ์Šค์ผ€์ด๋“œ ๊ณ„์‚ฐ, ShadowCoord๊ณ„์‚ฐ , Shadow Bias๊ณ„์‚ฐ
| |-- Shaders/
```

## 1์žฅ. ์…ฐ์ด๋” ๊ฐœ๋ฐœ ๊ณผ์ •

### Forward

``` ruby
for object in objects
for light in lights
FrameBuffer = LightModel(object, light);
end
end

for light in lights
for object in GetObjectsAffectedByLight(light)
FrameBuffer += LightModel(object, light);
end
end
```

![./forward-v2.png](./forward-v2.png)

๋ผ์ดํŠธ ๊ฐฏ์ˆ˜ ์ฆ๊ฐ€> ์—ฐ์‚ฐ๋Ÿ‰ ์ฆ๊ฐ€

### Deferred

``` ruby
for object in objects:
GBuffer = GetLightingProperties(object)
end

for light in lights
Framebuffer += LightModel(GBuffer, light)
end
```

![./deferred-v2.png](./deferred-v2.png)

- ๋ฐ˜ํˆฌ๋ช… ๋ถˆ๊ฐ€
- URP - ํ˜„์žฌ(10.3.1) deferred ์ง€์› ์•ˆํ•จ.
- [URP ๋กœ๋“œ๋งต](https://portal.productboard.com/8ufdwj59ehtmsvxenjumxo82/tabs/3-universal-render-pipeline)
- [๋ธ”๋ผ์ธ๋“œ ๋ Œ๋”๋Ÿฌ - ์ƒˆ๋กœ์šด ๊ธฐ๋ฒ• != ์ƒˆ ์žฅ๋‚œ๊ฐ](https://kblog.popekim.com/2012/02/blog-post.html)

## 2์žฅ. ์ฒซ ์œ ๋‹ˆํ‹ฐ ์…ฐ์ด๋”

- [Built-in vs URP](https://docs.unity3d.com/Packages/[email protected]/manual/universalrp-builtin-feature-comparison.html)

``` txt
Create> Rendering> Universal Render Pipeline> Pipeline Asset(Forward Renderer)

Assets/
|-- UniversalRenderPipelineAsset.asset
|-- UniversalRenderPipelineAsset_Renderer.asset

Project Settings> Graphics> Scriptable Render Pipeline Settings> UniversalRenderPipelineAsset.asset

UniversalRenderPipelineAsset.asset> Quality> HDR check

Project Settings> Player> Other Settings> Color Space> Linear
```

- [URP unlit basic shader](https://docs.unity3d.com/Packages/[email protected]/manual/writing-shaders-urp-basic-unlit-structure.html)

``` hlsl
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
Tags { "LightMode" = "SRPDefaultUnlit" } // ๋ผ์ดํŠธ ๋ชจ๋“œ ํƒœ๊ทธ ๊ธฐ๋ณธ๊ฐ’
```

- [URP ShaderLab Pass tags](https://docs.unity3d.com/Packages/[email protected]/manual/urp-shaders/urp-shaderlab-pass-tags.html)

| LightMode | URP Support |
|----------------------|-------------|
| UniversalForward | O |
| UniversalGBuffer | O |
| UniversalForwardOnly | O |
| Universal2D | O |
| ShadowCaster | O |
| DepthOnly | O |
| Meta | O |
| SRPDefaultUnlit | O(๊ธฐ๋ณธ๊ฐ’) |
| Always | X |
| ForwardAdd | X |
| PrepassBase | X |
| PrepassFinal | X |
| Vertex | X |
| VertexLMRGBM | X |
| VertexLM | X |

## 3์žฅ. ๊ทธ๋ž˜ํ”ฝ์Šค ํŒŒ์ดํ”„๋ผ์ธ

``` cs
// #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Core.hlsl"
// |-- #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/Common.hlsl"

// Core RP Library/ShaderLibrary/SpaceTransforms.hlsl

// UNITY_MATRIX_M * (UNITY_MATRIX_VP * positionOS)

float4 TransformObjectToHClip(float3 positionOS)
{
// More efficient than computing M*VP matrix product
return mul(GetWorldToHClipMatrix(), mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)));
}
```

## 4์žฅ. ์ขŒํ‘œ ๊ณต๊ฐ„ ๋ณ€ํ™˜

| Space | |
|-------|------------------------|
| WS | world space |
| VS | view space |
| OS | object space |
| CS | Homogenous clip spaces |
| TS | tangent space |
| TXS | texture space |

| built-in(legacy) | URP |
|--------------------------|------------------------------|
| UnityObjectToWorldDir | TransformObjectToWorldDir |
| UnityObjectToWorldNormal | TransformObjectToWorldNormal |
| UnityWorldSpaceViewDir | TransformWorldToViewDir |
| UnityWorldSpaceLightDir | x |

``` hlsl
float4x4 GetObjectToWorldMatrix() UNITY_MATRIX_M;
float4x4 GetWorldToObjectMatrix() UNITY_MATRIX_I_M;
float4x4 GetWorldToViewMatrix() UNITY_MATRIX_V;
float4x4 GetWorldToHClipMatrix() UNITY_MATRIX_VP;
float4x4 GetViewToHClipMatrix() UNITY_MATRIX_P;
```

| built-in(legacy) | URP |
|----------------------|------------------------|
| UnityObjectToClipPos | TransformObjectToHClip |
| UnityWorldToClipPos | TransformWorldToHClip |
| UnityViewToClipPos | TransformWViewToHClip |

-
-

## 5์žฅ. ์ตœ์ดˆ ๋ผ์ดํŒ… ์…ฐ์ด๋”

``` hlsl
// #include "Packages/com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl"
struct Light
{
half3 direction;
half3 color;
half distanceAttenuation;
half shadowAttenuation;
};

Light GetMainLight()
light.direction = _MainLightPosition.xyz;

Light GetMainLight(float4 shadowCoord)

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

// #include "Packages/com.unity.render-pipelines.core/ShaderLibrary/API/D3D11.hlsl"
#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2)
```

- [URP - Drawing a texture](https://docs.unity3d.com/Packages/[email protected]/manual/writing-shaders-urp-unlit-texture.html)

## 6์žฅ. ์ŠคํŽ™ํ˜๋Ÿฌ ๊ตฌํ˜„

- TODO ๋” ๋งŽ์€ ๊ด‘์› ์ง€์›ํ•˜๊ธฐ(2 Directional Light)
-

## 7์žฅ. ์„œํ”ผ์Šค ์…ฐ์ด๋”

- Surface๋Š” URP์—์„œ ์•ˆ์“ธ๊บผ๋ผ์„œ Vert/Frag๋กœ ๊ตฌํ˜„
- 2๊ฐœ Albedo๋ฅผ lerp์‹œํ‚ค๋Š”๊ฒƒ.
- NormapMap์ ์šฉ.

## 8์žฅ. ๋ฌผ๋ฆฌ ๊ธฐ๋ฐ˜ ์…ฐ์ด๋”ฉ์ด๋ž€?

- ๋น›์„ ์ธก์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•

| | ๋‹จ์œ„ | ์„ค๋ช… |
|-----------------------|--------------------|--------------------------------------------------|
| ์ž…์ฒด๊ฐ Solid Angle | sr(steradian) | ๋‹จ์œ„ ๊ตฌ๋กœ ์–ด๋– ํ•œ ํ˜•์ƒ์„ ์‚ฌ์˜ํ•œ ๊ฒƒ. |
| ํŒŒ์›Œ Power | W | ์—ฌ๋Ÿฌ ๋ฐฉํ–ฅ์—์„œ ํ‘œ๋ฉด์„ ํ†ต๊ณผํ•ด ์ „๋‹ฌ๋˜๋Š” ์—๋„ˆ์ง€ ํฌ๊ธฐ |
| ์ผ๋ ˆ๋””์•ˆ์Šค Irradiance | E (W/m^2) | ๋ชจ๋“  ๊ด‘์„ ์—์„œ ์ ์— ์ „๋‹ฌ๋˜๋Š” ๋น›์˜ ํฌ๊ธฐ |
| ๋ ˆ๋””์•ˆ์Šค Radiance | L_0 (W/(m^2 * sr)) | ํ•˜๋‚˜์˜ ๊ด‘์„ ์—์„œ ์ ์— ์ „๋‹ฌ๋˜๋Š” ๋น›์˜ ํฌ๊ธฐ |

- ์žฌ์งˆ์„ ํ‘œํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•

์–‘๋ฐฉํ–ฅ ๋ฐ˜์‚ฌ ๋ถ„ํฌ ํ•จ์ˆ˜ BRDF Bidirectional Reflectance Distribution Function
๋น›์ด ํ‘œ๋ฉด์—์„œ ์–ด๋–ป๊ฒŒ ๋ฐ˜์‚ฌ๋ ์ง€์— ๋Œ€ํ•ด ์ •์˜ํ•œ ํ•จ์ˆ˜.

| BRDF ์†์„ฑ | |
|------------------------|----------------------------------------------------------------------------------------------|
| positivity | BRDF๊ฐ’์€ 0์ด์ƒ์ด๋‹ค |
| symmetry (reciprocity) | ๋น›์ด ๋“ค์–ด์˜ค๋Š” ๋ฐฉํ–ฅ๊ณผ ๋ฐ˜์‚ฌ๋˜๋Š” ๋ฐฉํ–ฅ์˜ ๊ฐ’์€ ๋™์ผํ•˜๋‹ค |
| conservation of energy | ๋‚˜๊ฐ€๋Š” ๋น›์˜ ์–‘์€ ๋“ค์–ด์˜ค๋Š” ๋น›์˜ ์–‘์„ ๋„˜์–ด์„ค ์ˆ˜ ์—†๋‹ค(๋ฌผ์ฒด๊ฐ€ ์ž์ฒด์ ์œผ๋กœ ๋น›์„ ๋ฐœ์‚ฐํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด) |

## 9์žฅ. ๋ฌผ๋ฆฌ ๊ธฐ๋ฐ˜ ์…ฐ์ด๋” ์ œ์ž‘ํ•˜๊ธฐ

``` hlsl
half3 LightingPhong(half3 lightColor, half3 lightDir, half3 normal, half3 viewDir, half4 specularColor, half3 albedo, half shininess)
{
half NdotL = saturate(dot(normal, lightDir));
half3 diffuseTerm = NdotL * albedo * lightColor;

half3 reflectionDirection = reflect(-lightDir, normal);
half3 specularDot = max(0.0, dot(viewDir, reflectionDirection));
half3 specular = pow(specularDot, shininess);
half3 specularTerm = specularColor.rgb * specular * lightColor;

return diffuseTerm + specularTerm;
}

// Lafortune and Willems (1994)
half3 LightingPhongModified(half3 lightColor, half3 lightDir, half3 normal, half3 viewDir, half4 specularColor, half3 albedo, half shininess)
{
half NdotL = saturate(dot(normal, lightDir));
half3 diffuseTerm = NdotL * albedo * lightColor;

half norm = (shininess + 2) / (2 * PI);

half3 reflectionDirection = reflect(-lightDir, normal);
half3 specularDot = max(0.0, dot(viewDir, reflectionDirection));

half3 specular = norm * pow(specularDot, shininess);

half3 specularTerm = specularColor.rgb * specular * lightColor;

return diffuseTerm + specularTerm;
}
```

## 10์žฅ. ํ›„์ฒ˜๋ฆฌ ํšจ๊ณผ

``` hlsl
// com.unity.render-pipelines.core/ShaderLibrary/API/D3D11.hlsl
#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2)
#define SAMPLE_DEPTH_TEXTURE(textureName, samplerName, coord2) SAMPLE_TEXTURE2D(textureName, samplerName, coord2).r
```

``` hlsl
// com.unity.render-pipelines.core/ShaderLibrary/API/Common.hlsl
// Z buffer to linear 0..1 depth (0 at near plane, 1 at far plane).
// Does NOT correctly handle oblique view frustums.
// Does NOT work with orthographic projection.
// zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f }
float Linear01DepthFromNear(float depth, float4 zBufferParam)
{
return 1.0 / (zBufferParam.x + zBufferParam.y / depth);
}

// Z buffer to linear 0..1 depth (0 at camera position, 1 at far plane).
// Does NOT work with orthographic projections.
// Does NOT correctly handle oblique view frustums.
// zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f }
float Linear01Depth(float depth, float4 zBufferParam)
{
return 1.0 / (zBufferParam.x * depth + zBufferParam.y);
}

// Z buffer to linear depth.
// Does NOT correctly handle oblique view frustums.
// Does NOT work with orthographic projection.
// zBufferParam = { (f-n)/n, 1, (f-n)/n*f, 1/f }
float LinearEyeDepth(float depth, float4 zBufferParam)
{
return 1.0 / (zBufferParam.z * depth + zBufferParam.w);
}

// Z buffer to linear depth.
// Correctly handles oblique view frustums.
// Does NOT work with orthographic projection.
// Ref: An Efficient Depth Linearization Method for Oblique View Frustums, Eq. 6.
float LinearEyeDepth(float2 positionNDC, float deviceDepth, float4 invProjParam)
{
float4 positionCS = float4(positionNDC * 2.0 - 1.0, deviceDepth, 1.0);
float viewSpaceZ = rcp(dot(positionCS, invProjParam));

// If the matrix is right-handed, we have to flip the Z axis to get a positive value.
return abs(viewSpaceZ);
}

// Z buffer to linear depth.
// Works in all cases.
// Typically, this is the cheapest variant, provided you've already computed 'positionWS'.
// Assumes that the 'positionWS' is in front of the camera.
float LinearEyeDepth(float3 positionWS, float4x4 viewMatrix)
{
float viewSpaceZ = mul(viewMatrix, float4(positionWS, 1.0)).z;

// If the matrix is right-handed, we have to flip the Z axis to get a positive value.
return abs(viewSpaceZ);
}
```

| | Built-in | URP |
|--------|---------------|-----------------------|
| Camera | Camera: | RenderPipelineManager |
| | OnPreCull | beginFrameRendering |
| | OnPreRender | beginCameraRendering |
| | OnPostRender | endCameraRendering |
| | OnRenderImage | endFrameRendering |

`Create> Rendering> Universal Render Pipeline> Renderer Feature`

| | ์ž๋™ ์ƒ์„ฑ๋จ | |
|----------------------------|-------------|-----------------------------------|
| _CameraDepthTexture | O | Pipeline Settings> Depth Texture |
| _CameraOpaqueTexture | O | Pipeline Settings> Opaque Texture |
| _CameraColorTexture | ?? | |
| _CameraDepthNormalsTexture | X | |

-

``` txt
- Camera> Rendering> Post-Processing ์ฒดํฌ
- Hierachy> Volume> Global Volume
- Global Volume> Volume> Profile> New
- Global Volume> Volume> Add Override
```

## 11์žฅ. BRDF ๋ˆ„๊ฐ€ ๋ˆ„๊ตฌ์ธ๊ฐ€?

-
-
-
- [[ ๋ฒˆ์—ญ ] Physically-Based Shading at Disney](https://lifeisforu.tistory.com/350)

![./brdf_vectors.png](./brdf_vectors.png)

| ๊ธฐํ˜ธ | ์„ค๋ช… |
|------|-----------------------------------|
| N | ๋…ธ๋ง |
| H | ํ•˜ํ”„๋ฒกํ„ฐ `H = normalize( L + V )` |
| L | ๋ผ์ดํŠธ(๊ด‘์›) |
| V | ๋ทฐ(์นด๋ฉ”๋ผ) |
| T | ํƒ„์  ํŠธ |
| ฮ˜ | (Theta) ๋ฐฉ์œ„๊ฐ |
| ฮฆ | (Phi) ์•™๊ฐ(์˜ฌ๋ ค๋ณธ๊ฐ) |

### BRDF ์ข…๋ฅ˜

#### Ashikhmin Shirley ์–ดํฌ๋จผ ์…œ๋ฆฌ

2000 - Michael Ashikhmin & Peter Shirley - An Anisotropic Phong BRDF Model

ํ ์ŠคํŽ™ํ˜๋Ÿฌ

#### Cook Torrance ์ฟกํ† ๋ Œ์Šค

1982 - Robert L.Cook & Kenneth E. Torrance - A Reflectance Model For Computer Graphics

๋ฏธ์„ธ๋ฉด์ด๋ก 

#### Oren Nayar ์˜ค๋ Œ๋„ค์ด์–ด

1994 - Michael Oren & Shree K. Nayar - Generalization of Lambertโ€™s Reflectance Model

๋””ํ“จ์ฆˆ ์ „์šฉ

#### Ward ์•Œ๋“œ

1992 - Gregory J. Ward - Measuring and modeling anisotropic reflection

๊ฒฝํ—˜์  ๋ฐ์ดํ„ฐ ๊ธฐ๋ฐ˜, ๊ฑฐ์˜ ์‚ฌ์šฉ๋˜์ง€ ์•Š์Œ.

#### Disney ๋””์ฆˆ๋‹ˆ

SIGGRAPH 2012 - Brent Burley - Physically Based Shading at Disney

์—ฌ๋Ÿฌ ํŒŒ๋ผ๋ฏธํ„ฐ

## 12์žฅ. BRDF ๊ตฌํ˜„ํ•˜๊ธฐ

- ์ฐธ๊ณ 
- [[NDC19] ๋ชจ๋ฐ”์ผ์—์„œ ์‚ฌ์šฉ๊ฐ€๋Šฅํ•œ ์œ ๋‹ˆํ‹ฐ ์ปค์Šคํ…€ ์„ญ์Šคํ„ด์Šค PBR ์…ฐ์ด๋” ๋งŒ๋“ค๊ธฐ](https://www.slideshare.net/dongminpark71/ndc19-pbr-143928930)

### ๋ ˆํผ๋Ÿฐ์Šค BRDF

#### Cook Torrance ๋ ˆํผ๋Ÿฐ์Šค

| | |
|--------------------------------------------------------------------------------------|--------------------------------------------------------------------|
| Physics and Math of Shading by Naty Hoffman | SIGGRAPH every year from 2012 to 2015 |
| Real Shading in Unreal Engine 4 by Brian Karis | SIGGRAPH, 2013 |
| BRDF Explorer (GLSL) - CookTorrance BRDF | |
| Specular BRDF Reference on Brian Karisโ€™ blog | |
| Introduction to BRDF Models by Daniรซl Jimenez Kwast | |
| A Reflectance Model for Computer Graphics from 1981 | |
| Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs by Eric Heitz | SIGGRAPH, 2014 - ๋ฏธ์„ธ๋ฉด์ดํ•ด ์ถ”์ฒœ |
| Microfacet Models for Refraction through Rough Surfaces | EGSR, 2017 |

#### Disney ๋ ˆํผ๋Ÿฐ์Šค

| | |
|---------------------------------------------------------------------------|------------------------------------------------------------------------------------|
| Physically Based Shading at Disney | SIGGRAPH, 2012, by Brent Burley |
| BRDF Explorer (GLSL) - Disney BRDF | |
| Extending the Disney BRDF to a BSDF with Integrated Subsurface Scattering | SIGGRAPH, 2015, by Brent Burley |
| Moving Frostbite to Physically Based Rendering | SIGGRAPH, 2015, by Sรฉbastien Lagarde and Charlesde Rousiers (only for the Diffuse) |

### ์ด๋ก  BRDF

#### Cook Torrance ์ด๋ก 

๋ฏธ์„ธ๋ฉด ์ด๋ก 
| | | | ๊ด€์—ฌ ๋ฒกํ„ฐ | | |
|---|--------------------------------|--------------|-----------|-------|-------------------------------------------------------------------|
| D | Normal `Distribution` Function | ์ •๊ทœ๋ถ„ํฌํ•จ์ˆ˜ | (H) | ์–‘์ˆ˜ | ํฌ๊ธฐ, ๋ฐ๊ธฐ, ์ŠคํŽ™ํ˜๋Ÿฌ ๋ชจ์–‘ |
| F | Fresnel | ํ”„๋ ˆ๋„ฌ | (L, H) | 0 ~ 1 | ๋ณด๋Š” ๊ฐ๋„์— ๋”ฐ๋ฅธ ๋ฐ˜์‚ฌ์œจ๊ณผ ๊ตด์ ˆ์œจ |
| G | Geometry | ๊ธฐํ•˜ํ•จ์ˆ˜ | (L, V, H) | | ๋ฉด์ด ์„œ๋กœ ๊ฒน์ณ์„œ ๋น›์„ ์ฐจ๋‹จํ•˜๋Š” ์ •๋„์˜ ๊ทผ์‚ฌ์น˜๋ฅผ ํ†ต๊ณ„์ ์œผ๋กœ ๊ตฌํ•œ๋‹ค. |

- NDF (Normal `Distribution` Function)
- Beckmann
- Phong
- GGX

์ฑ…์˜ ๊ตฌํ˜„์—์„œ๋Š”

| | |
|---|----------------------|
| D | Trowbridge-Reitz GGX |
| F | Fresnel-Schlick |
| G | Smith's Schlick-GGX |

#### Disney ์ด๋ก 

### ๊ตฌํ˜„ BRDF

#### Cook Torrance ๊ตฌํ˜„

#### Disney ๊ตฌํ˜„

## 13์žฅ. ํ‘œ์ค€ ์…ฐ์ด๋” ํ›„ํ‚น

- 16์žฅ. ๋ณต์žก๋„์™€ ์šฐ๋ฒ„์…ฐ์ด๋” ์ฐธ์กฐ.

``` hlsl
// com.unity.render-pipelines.universal/ShaderLibrary/Lighting.hlsl

struct BRDFData
{
half3 albedo;
half3 diffuse;
half3 specular;
half reflectivity;
half perceptualRoughness;
half roughness;
half roughness2;
half grazingTerm;

// We save some light invariant BRDF terms so we don't have to recompute
// them in the light loop. Take a look at DirectBRDF function for detailed explaination.
half normalizationTerm; // roughness * 4.0 + 2.0
half roughness2MinusOne; // roughness^2 - 1.0
};
```

- [Custom Shader GUI](https://docs.unity3d.com/2021.1/Documentation/Manual/SL-CustomShaderGUI.html)
- [ShaderGUI: Custom Material Inspectors in Unity 5+](https://www.alanzucconi.com/2016/11/07/shadergui-custom-material-inspectors-unity-5/)

## 14์žฅ. ๊ณ ๊ธ‰ ๊ธฐ์ˆ  ๊ตฌํ˜„

### ๋ฐ˜ํˆฌ๋ช… (Translucency)

๋ฐ˜ํˆฌ๋ช…์€ BRDF๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๊ณค๋ž€.
| | | |
|------|---------------------------------------------------|------------------------------------------------|
| BRDF | Bidirectional reflectance distribution function | ๋Š” ๋น›์ด ์–ด๋–ค ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ˜์‚ฌ๊ฐ€ ๋˜๋Š”์ง€ |
| BTDF | Bidirectional transmittance distribution function | ๋Š” ๋น›์ด ์–ด๋–ค ๋ฐฉํ–ฅ์œผ๋กœ ํˆฌ๊ณผ๊ฐ€ ๋˜๋Š”์ง€ |
| BSDF | Bidirectional scattering distribution function | ์ด ๋‘˜์„ ํ•ฉ์ณ ๋น›์ด ์žฌ์งˆ๊ณผ ์–ด๋–ป๊ฒŒ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š”์ง€ |

- TODO ์˜ˆ์ œ์—์„œ 2๊ฐœ์˜ Directional Light์‚ฌ์šฉ...

``` hlsl
// ref: GPG Pro 2

//Translucency
// - ๋…ธ๋ง๊ณผ ๋ผ์ดํŠธ์˜ ํ•˜ํ”„์˜ ์—ญ๋ฐฉํ–ฅ์— (๋ฌผ์ฒด ๋’ท๋ถ€๋ถ„)
// - ๋ทฐ๋ฅผ ๋‹ท์—ฐ์‚ฐ์œผ๋กœ ๋ฌถ์–ด์ค€๋‹ค. (ํ™•์‚ฐํšจ๊ณผ)

float thickness = SAMPLE_TEXTURE2D(_Thickness, sampler_Thickness, IN.uv).r;
float3 translucencyLightDir = L + N * _Distortion;
float translucencyDot = pow(saturate(dot(V, -translucencyLightDir)), _Power) * _Scale;
float3 translucency = translucencyDot * thickness * _SubsurfaceColor.rgb;
diffuse += translucency;
```

### IBL

-

| Cubemap์ƒ์„ฑ ๋„๊ตฌ | |
|----------------------------------------------------------|-------------|
| [cmftStudio](https://github.com/dariomanesku/cmftStudio) | BSD 2 |
| [Knald's Lys](https://www.knaldtech.com/lys/) | Commercial |
| [IBLBaker](https://github.com/derkreature/IBLBaker) | MIT License |
| [CubeMapGen](https://gpuopen.com/archived/cubemapgen/) | old |

## 15์žฅ. ์•„ํ‹ฐ์ŠคํŠธ๊ฐ€ ์‚ฌ์šฉํ•  ์…ฐ์ด๋” ์ œ์ž‘

์•„ํ‹ฐ์ŠคํŠธ๊ฐ€ ์กฐ์ž‘ํ•˜๊ธฐ ํŽธํ•˜๊ฒŒ

1. ์ ์ ˆํ•œ ์…‹ํŒ… ๊ฐฏ์ˆ˜
2. ์ ์ ˆํ•œ ์…‹ํŒ… ๋„ค์ด๋ฐ
3. ์ƒํ˜ธ ์ž‘์šฉํ•˜๋Š” ์…‹ํŒ…๊ฐ’์„ ์œ„ํ•œ ๋ฌธ์„œํ™”
4. ํ…์Šค์ณ์— ์—ฌ๋Ÿฌ ์ •๋ณด(albedo + specular๋“ฑ)์„ ๋„ฃ๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ์€๋ฐ, ๋ช…ํ™•ํ•˜๊ฒŒ ์…‹ํŒ…๊ฐ’๊ณผ ์…‹ํŒ… ๋„ค์ด๋ฐ์„ ํ‘œ์‹œ
5. ์—ฌ๋Ÿฌ ๋ฒ”์œ„ ํ˜ผํ•ฉ์‚ฌ์šฉ ํ”ผํ•˜๊ธฐ(๋˜๋„๋ก์ด๋ฉด `0 ~ 1`๋กœ...)

ํŒŒ๋ผ๋ฏธํ„ฐ ๋ณ€ํ™”๊ฐ’ ๋ณ„๋กœ ์˜ˆ์ œ ์”ฌ ์žˆ์œผ๋ฉด ์ข‹๊ฒ ๋„ค..

## 16์žฅ. ๋ณต์žก๋„์™€ ์šฐ๋ฒ„์…ฐ์ด๋”

์‰์ด๋” ํ•˜๋‚˜๋ฅผ ์ด์šฉํ•ด์„œ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ๊ฒฝ์šฐ๋ฅผ ์ฒ˜๋ฆฌํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ, ํ•„์š”ํ•œ ๋ชจ๋“  ์ฝ”๋“œ๋ฅผ ์‰์ด๋” ํ•˜๋‚˜์— ์ง‘์–ด๋„ฃ๊ฒŒ๋˜๋ฉด ๊ทธ๊ฒŒ ๋ฐ”๋กœ ์šฐ๋ฒ„์…ฐ์ด๋”.

- `if`์™€ ๊ฐ™์€ ๋™์ ๋ถ„๊ธฐ๋Š” ์„ฑ๋Šฅ์ €ํ•˜.
- `#if`์™€ ๊ฐ™์ด ์ „์ฒ˜๋ฆฌ๊ธฐ๋ฅผ ์ด์šฉํ•œ, ์ •์  ๋ถ„๊ธฐ๋ฅผ ์ด์šฉํ•˜์—ฌ ์ฒ˜๋ฆฌํ•œ๋‹ค.

์œ ๋‹ˆํ‹ฐ์—์„œ๋Š” ํ‚ค์›Œ๋“œ๋ฅผ ์ด์šฉ ์‰์ด๋” ์กฐํ•ฉ์„ ํŽธ๋ฆฌํ•˜๊ฒŒ ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด ์žˆ์Œ.

- [Shader variants and keywords](https://docs.unity3d.com/2021.1/Documentation/Manual/SL-MultipleProgramVariants.html)
- ์ด 256๊ฐœ์˜ ๊ธ€๋กœ๋ฒŒ ํ‚ค์›Œ๋“œ.
- 64๊ฐœ์˜ ๋กœ์ปฌ ํ‚ค์›Œ๋“œ.

- `#pragma shader_feature KEYWORD`
- `#pragma multi_compile KEYWORD`

| | ๊ฒŒ์ž„๋นŒ๋“œ์— ํฌํ•จ |
|----------------|---------------------|
| shader_feature | ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ๋งŒ |
| multi_compile | ์กฐํ•ฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๊ฒƒ |

``` txt
#pragma multi_compile A B C
#pragma multi_compile D E

์กฐํ•ฉํ•ด์„œ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋Š” ์ด ๊ฐฏ์ˆ˜: 6๊ฐœ
A+D, B+D, C+D
A+E, B+E, C+E
```

``` hlsl
[KeywordEnum(Off, On)] _UseNormal("Use Normal Map", Float) = 0
#pragma shader_feature _USENORMAL_OFF _USENORMAL_ON
#if _USENORMAL_ON
#endif

[Toggle] _ModifiedMode("Modified?", Float) = 0
#pragma shader_feature _MODIFIEDMODE_OFF _MODIFIEDMODE_ON
#if _MODIFIEDMODE_ON
#endif
```

## 17์žฅ. ์…ฐ์ด๋”๊ฐ€ ์ •์ƒ์ž‘๋™ํ•˜์ง€ ์•Š์„ ๋•Œ

### ์ผ๋ฐ˜์  ํŠธ๋ฆญ

- shader๋กœ ๋…ธ๋ง๊ฐ’ ์‹œ๊ฐํ™”

``` hlsl
struct Attributes
{
float4 positionOS : POSITION;
float3 normalOS : NORMAL;
float4 tangent : TANGENT;
float2 uv : TEXCOORD0;
};

struct Varyings
{
float4 positionHCS : SV_POSITION;
float2 uv : TEXCOORD0;

float3 T : TEXCOORD1;
float3 B : TEXCOORD2;
float3 N : TEXCOORD3;

float3 positionWS : TEXCOORD4;
};

// ----------
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)));
}

Varyings vert(Attributes IN)
{
//Varyings OUT;
Varyings OUT = (Varyings)0;;
OUT.positionHCS = TransformObjectToHClip(IN.positionOS.xyz);
OUT.uv = TRANSFORM_TEX(IN.uv, _BumpMap);

ExtractTBN(IN.normalOS, IN.tangent, OUT.T, OUT.B, OUT.N);

OUT.positionWS = TransformObjectToWorld(IN.positionOS.xyz);
return OUT;
}

// ---------------
half4 frag(Varyings IN) : SV_Target
{
#if _ENABLENORMALMAP_ON
float3 tangentNormal = UnpackNormal(SAMPLE_TEXTURE2D(_BumpMap, sampler_BumpMap, IN.uv));
tangentNormal.xy *= _BumpMapStrength; // BumpMap Strength.

float3 N = CombineTBN(tangentNormal, IN.T, IN.B, IN.N);
#else
float3 N = normalize(IN.N);
#endif
return half4(N * 0.5 + 0.5, 1);
}
```

### ๋””๋ฒ„๊น… ๋„๊ตฌ

- Window> Analysis> Frame Debugger
- RenderDoc ํ”„๋กœ๊ทธ๋žจ
-

### ํ”„๋กœํŒŒ์ผ๋ง

| | |
|---------------------------------|--|
| ๋ฐฐ์น˜ ์ˆ˜ | |
| ๋“œ๋กœ์šฐ์ฝœ | |
| SetPass | |
| Vertex | |
| ํ…์Šค์ณ ๊ฐฏ์ˆ˜/๋ฉ”๋ชจ๋ฆฌ /์Šค์œ„์น˜ ํšŸ์ˆ˜ | |
| Shadow Casters | |
| Vertex Buffer Object | |

- CPU์— ์น˜์ค‘? GPU์— ์น˜์ค‘?
- Static GameObject ํ™œ์šฉ ์ž˜ํ•˜๊ธฐ.

## 18์žฅ. ์ตœ์„  ํŠธ๋ Œ๋“œ ๋”ฐ๋ผ์žก๊ธฐ

### ์ปจํผ๋Ÿฐ์Šค

| | |
|-----------------|------------------------------|
| GDC | GDC Vault ๊ตฌ๋… 1๋…„ 400๋ถˆ์ •๋„ |
| Siggraph | 1๋…„ 45๋‹ฌ๋Ÿฌ |
| Unite | |
| Digital Dragons | ์˜์ƒ์ž๋ฃŒ ๊ณต๊ฐœ |
| Eurographics | ํ•™์ˆ ์œ„์ฃผ |

### ์„œ์ 

์–ด๋ ต์ง€๋งŒ ๊ตฌ์ž…ํ•ด์„œ ์ฝ์–ด๋ณผ ๊ฐ€์น˜ ์žˆ์Œ.

| | |
|----------|--|
| GPU Gems | |
| ShaderX | |
| GPU PRO | |
| GPU Zen | |

### ์‚ฌ์ดํŠธ

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

## etc

- [Microfacet BRDF](http://www.pbr-book.org/3ed-2018/Reflection_Models/Microfacet_Models.html#)
-