Skip to content

netpyoung/bs.physically_based_shader_develop_for_unity

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

22 Commits
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 
ย 

Repository files navigation

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

./physically-based-shader-dev-for-unity-2017.jpg

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

URP (Universal Render Pipeline)

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

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

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

Deferred

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

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

./deferred-v2.png

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

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
Tags { "RenderType" = "Opaque" "RenderPipeline" = "UniversalPipeline" }
Tags { "LightMode" = "SRPDefaultUnlit" } // ๋ผ์ดํŠธ ๋ชจ๋“œ ํƒœ๊ทธ ๊ธฐ๋ณธ๊ฐ’
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์žฅ. ๊ทธ๋ž˜ํ”ฝ์Šค ํŒŒ์ดํ”„๋ผ์ธ

// #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
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์žฅ. ์ตœ์ดˆ ๋ผ์ดํŒ… ์…ฐ์ด๋”

// #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)

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

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์žฅ. ๋ฌผ๋ฆฌ ๊ธฐ๋ฐ˜ ์…ฐ์ด๋” ์ œ์ž‘ํ•˜๊ธฐ

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์žฅ. ํ›„์ฒ˜๋ฆฌ ํšจ๊ณผ

// 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
// 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
- Camera> Rendering> Post-Processing ์ฒดํฌ
- Hierachy> Volume> Global Volume
- Global Volume> Volume> Profile> New
- Global Volume> Volume> Add Override

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

./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 ๊ตฌํ˜„ํ•˜๊ธฐ

๋ ˆํผ๋Ÿฐ์Šค 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 <graphicrants.blogspot.co.uk/2013/08/specular-brdf-reference.html>
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์žฅ. ๋ณต์žก๋„์™€ ์šฐ๋ฒ„์…ฐ์ด๋” ์ฐธ์กฐ.
// 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
};

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

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

๋ฐ˜ํˆฌ๋ช…์€ BRDF๋กœ ์ฒ˜๋ฆฌํ•˜๊ธฐ ๊ณค๋ž€.

BRDF Bidirectional reflectance distribution function ๋Š” ๋น›์ด ์–ด๋–ค ๋ฐฉํ–ฅ์œผ๋กœ ๋ฐ˜์‚ฌ๊ฐ€ ๋˜๋Š”์ง€
BTDF Bidirectional transmittance distribution function ๋Š” ๋น›์ด ์–ด๋–ค ๋ฐฉํ–ฅ์œผ๋กœ ํˆฌ๊ณผ๊ฐ€ ๋˜๋Š”์ง€
BSDF Bidirectional scattering distribution function ์ด ๋‘˜์„ ํ•ฉ์ณ ๋น›์ด ์žฌ์งˆ๊ณผ ์–ด๋–ป๊ฒŒ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š”์ง€
  • TODO ์˜ˆ์ œ์—์„œ 2๊ฐœ์˜ Directional Light์‚ฌ์šฉ...
// 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 BSD 2
Knald's Lys Commercial
IBLBaker MIT License
CubeMapGen old

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

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

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

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

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

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

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

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

  • Shader variants and keywords

  • ์ด 256๊ฐœ์˜ ๊ธ€๋กœ๋ฒŒ ํ‚ค์›Œ๋“œ.

  • 64๊ฐœ์˜ ๋กœ์ปฌ ํ‚ค์›Œ๋“œ.

  • #pragma shader_feature KEYWORD

  • #pragma multi_compile KEYWORD

๊ฒŒ์ž„๋นŒ๋“œ์— ํฌํ•จ
shader_feature ์‚ฌ์šฉ๋˜๋Š” ๊ฒƒ๋งŒ
multi_compile ์กฐํ•ฉ ๊ฐ€๋Šฅํ•œ ๋ชจ๋“  ๊ฒƒ
#pragma multi_compile A B C
#pragma multi_compile D E

์กฐํ•ฉํ•ด์„œ ๋‚˜์˜ฌ ์ˆ˜ ์žˆ๋Š” ์ด ๊ฐฏ์ˆ˜: 6๊ฐœ
A+D, B+D, C+D
A+E, B+E, C+E
[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๋กœ ๋…ธ๋ง๊ฐ’ ์‹œ๊ฐํ™”
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);
}

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

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

๋ฐฐ์น˜ ์ˆ˜
๋“œ๋กœ์šฐ์ฝœ
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

About

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

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published