Deferred Shading

                 http://ohyecloudy.com
      http://cafe.naver.com/shader.cafe
                              2009.03.30
Introduction
• 보통 사용하는 Forward Shading에서는 라이
  팅 비용이 비싸다.
 – 각각의 오브젝트마다 라이팅
 – 게임에서 사용하는 라이트 개수가 많아지고 있다.
• G-buffer에 라이팅 재료들을 렌더링하고 라
  이팅에 오브젝트들 대신 G-buffer를 사용.
 – 라이팅 비용을 줄인다.
 – Deferred Shading
Three major options for
       real-time lighting
• Forward Rendering
  – single pass with multiple lights
  – multiple passes with multiple lights lighting


• Deferred Rendering
Single-pass, multi-light
for each object do
  for each light do
    framebuffer = light_model(object,light);
Frame

Buffer
문제점
• 화면에 렌더링 되지 않을 Geometry도 라
  이팅 연산을 한다.
• 멀티 라이트일때 관리가 어렵다.
 – 싱글 셰이더 템플릿을 사용하기 때문에 조합
   하는 가지수가 폭발적으로 늘어난다.
Multi-pass, multi-light
for each light do
  for each object affected by light do
    framebuffer += light_model(object,light);
Previous
 Frame
 Buffer




Current
 Frame
 Buffer
문제점
• 화면에 렌더링 되지 않을 Geometry도 라
  이팅 연산을 한다.
• 높은 배치 카운트
 – 1/object/light
• 각 패스마다 중복된 작업이 많다.
 – Vertex transform & setup
Deferred Shading
for each object do
  G-buffer = lighting properties of object;
for each light do
  framebuffer += light_model(G-buffer,light);
G-Buffer




Previous              Current
 Frame                 Frame
 Buffer                Buffer
특징
• 배치가 갂단해지고 관리가 쉽다
• 그림자 테크닉과 통합이 쉽다.
• 라이팅이 O(1)에 가능
 – 오브젝트 개수에 상관 없다.
G-Buffer
• Per-pixel lighting에 필요한 모든 정보
 – Normal
 – Position
 – Diffuse / Specular Albedo, other attributes
Normal
Depth
Diffuse
Specular factor
Computing Lighting
For each light:
    diffuse += diffuse(G-buff.N, L))
    specular += G-buff.spec *
         specular(G-buff.N, G-buff.P, L)
Diffuse Lighting
Specular reflection
Deferred Composition
framebuffer
  = diffuse * G-buff.diffuse + specular
Shader code
• Writing G-buffer
• Lighting
Writing G-buffer
PS_MRT_OUTPUT SimplePS(VS_OUTPUT0 In)
{
         PS_MRT_OUTPUT Out;

        half4 diffuseTex = tex2D( DiffuseMapSampler, In.TexCoord0);
        half3 normalTex = tex2D( NormalMapSampler, In.TexCoord1);

        diffuseTex.xyz = diffuseTex.w;

        //put normal into view space
        float3x3 TangentToView;
        TangentToView[0] = In.TangentToView0;
        TangentToView[1] = In.TangentToView1;
        TangentToView[2] = In.TangentToView2;
        half3 normal = normalize(mul(normalTex, TangentToView));

        //pack
        normal = normal * 0.5f + 0.5f;

        Out.Color0 = float4(diffuseTex.xyz, NotShadowed);
        Out.Color1 = float4(normal, 0.0);
        Out.Color2 = float4(In.Position2.z / In.Position2.w, 0.0f, 0.0f, 0.0f);

        return Out;
}
Per-Pixel Lighting
float4 DirLightingPS(VS_OUTPUT1 In) : COLOR
{
       half4 diffuseTex = tex2D(MRT0Sampler, In.TexCoord);
       half4 normalTex   = tex2D(MRT1Sampler, In.TexCoord);
       half z            = tex2D(MRT2Sampler, In.TexCoord);

      //reconstruct original view-space position
      float x = In.Position2.x;
      float y = In.Position2.y;
      float4 position = mul(float4(x, y, z, 1.0), InvProj);
      position.xyz = position.xyz / position.www;
      position.w = 1.0f;

      //compute position in light space
      …
      //diffuse lighting
      finalLighting = shadow * diffuse + Ambient + emissive;
      return float4(finalLighting, 1.0f);
}
극복해야 할 사항
• Transparency
  – alpha blending
  – G-buffer는 하나의 픽셀만 저장하기 때문에
    Forward Rendering처럼 갂단하지 않다.
• Anti-Aliasing
  – Forward Rendering처럼 frame buffer에 직접
    렌더링할때 자동으로 받는 하드웨어 anti-
    aliasing이 불가능
결론
• O(1)에 Lighting을 할 수 있다.
 – 오브젝트 개수에 상관없이 상수 시갂에 라이
   팅이 가능하다.
• 사용하는 렌더 타겟의 개수가 늘어나는게
  부담.
• Transparency, AA 등 극복해야 하는 문제
  점들이 존재.
참고
• Deferred Shading – NVIDIA
• Deferred Rendering in Leadwerks Engine
• HDR Deferred Shading – NVIDIA SDK

Deferred Shading

  • 1.
    Deferred Shading http://ohyecloudy.com http://cafe.naver.com/shader.cafe 2009.03.30
  • 2.
    Introduction • 보통 사용하는Forward Shading에서는 라이 팅 비용이 비싸다. – 각각의 오브젝트마다 라이팅 – 게임에서 사용하는 라이트 개수가 많아지고 있다. • G-buffer에 라이팅 재료들을 렌더링하고 라 이팅에 오브젝트들 대신 G-buffer를 사용. – 라이팅 비용을 줄인다. – Deferred Shading
  • 3.
    Three major optionsfor real-time lighting • Forward Rendering – single pass with multiple lights – multiple passes with multiple lights lighting • Deferred Rendering
  • 4.
    Single-pass, multi-light for eachobject do for each light do framebuffer = light_model(object,light);
  • 5.
  • 6.
    문제점 • 화면에 렌더링되지 않을 Geometry도 라 이팅 연산을 한다. • 멀티 라이트일때 관리가 어렵다. – 싱글 셰이더 템플릿을 사용하기 때문에 조합 하는 가지수가 폭발적으로 늘어난다.
  • 7.
    Multi-pass, multi-light for eachlight do for each object affected by light do framebuffer += light_model(object,light);
  • 8.
  • 9.
    문제점 • 화면에 렌더링되지 않을 Geometry도 라 이팅 연산을 한다. • 높은 배치 카운트 – 1/object/light • 각 패스마다 중복된 작업이 많다. – Vertex transform & setup
  • 10.
    Deferred Shading for eachobject do G-buffer = lighting properties of object; for each light do framebuffer += light_model(G-buffer,light);
  • 11.
    G-Buffer Previous Current Frame Frame Buffer Buffer
  • 12.
    특징 • 배치가 갂단해지고관리가 쉽다 • 그림자 테크닉과 통합이 쉽다. • 라이팅이 O(1)에 가능 – 오브젝트 개수에 상관 없다.
  • 13.
    G-Buffer • Per-pixel lighting에필요한 모든 정보 – Normal – Position – Diffuse / Specular Albedo, other attributes
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
    Computing Lighting For eachlight: diffuse += diffuse(G-buff.N, L)) specular += G-buff.spec * specular(G-buff.N, G-buff.P, L)
  • 19.
  • 20.
  • 21.
    Deferred Composition framebuffer = diffuse * G-buff.diffuse + specular
  • 23.
    Shader code • WritingG-buffer • Lighting
  • 24.
    Writing G-buffer PS_MRT_OUTPUT SimplePS(VS_OUTPUT0In) { PS_MRT_OUTPUT Out; half4 diffuseTex = tex2D( DiffuseMapSampler, In.TexCoord0); half3 normalTex = tex2D( NormalMapSampler, In.TexCoord1); diffuseTex.xyz = diffuseTex.w; //put normal into view space float3x3 TangentToView; TangentToView[0] = In.TangentToView0; TangentToView[1] = In.TangentToView1; TangentToView[2] = In.TangentToView2; half3 normal = normalize(mul(normalTex, TangentToView)); //pack normal = normal * 0.5f + 0.5f; Out.Color0 = float4(diffuseTex.xyz, NotShadowed); Out.Color1 = float4(normal, 0.0); Out.Color2 = float4(In.Position2.z / In.Position2.w, 0.0f, 0.0f, 0.0f); return Out; }
  • 25.
    Per-Pixel Lighting float4 DirLightingPS(VS_OUTPUT1In) : COLOR { half4 diffuseTex = tex2D(MRT0Sampler, In.TexCoord); half4 normalTex = tex2D(MRT1Sampler, In.TexCoord); half z = tex2D(MRT2Sampler, In.TexCoord); //reconstruct original view-space position float x = In.Position2.x; float y = In.Position2.y; float4 position = mul(float4(x, y, z, 1.0), InvProj); position.xyz = position.xyz / position.www; position.w = 1.0f; //compute position in light space … //diffuse lighting finalLighting = shadow * diffuse + Ambient + emissive; return float4(finalLighting, 1.0f); }
  • 26.
    극복해야 할 사항 •Transparency – alpha blending – G-buffer는 하나의 픽셀만 저장하기 때문에 Forward Rendering처럼 갂단하지 않다. • Anti-Aliasing – Forward Rendering처럼 frame buffer에 직접 렌더링할때 자동으로 받는 하드웨어 anti- aliasing이 불가능
  • 27.
    결론 • O(1)에 Lighting을할 수 있다. – 오브젝트 개수에 상관없이 상수 시갂에 라이 팅이 가능하다. • 사용하는 렌더 타겟의 개수가 늘어나는게 부담. • Transparency, AA 등 극복해야 하는 문제 점들이 존재.
  • 28.
    참고 • Deferred Shading– NVIDIA • Deferred Rendering in Leadwerks Engine • HDR Deferred Shading – NVIDIA SDK