Transcript
Page 1: Light in screen_space(Light Pre Pass)

Lighting In Screen Space(Light Pre-Pass)

이민웅

Page 2: Light in screen_space(Light Pre Pass)

차례 많은 광원을 그리는 방법들

Deferred Shading Light Pre-Pass 소개 Light Pre-Pass 구현방법

GBuffer Light Buffer

정리 질문

Page 3: Light in screen_space(Light Pre Pass)

많은 광원을 그리는 방법들 Deferred Shading / Rendering

Saito & Takahashi 1990 Z Pre Pass Rendering

John D. Carmack II, Doom3 Light Pre Pass

Wolfgang Engel 2008

Inferred Lighting SIGGRAPH2009 Scott Kircher,Alan Lawrance

Page 4: Light in screen_space(Light Pre Pass)

Z Pre Pass Rendering 존카멕이 처음 개발 Doom3 적용 Depth 만을 가지고 Light 계산

Page 5: Light in screen_space(Light Pre Pass)

Deferred Shading 굉장히 배치가 간단해지고 , 엔진에서 관리가 쉽다

일반적인 그림자 테크닉들과 통합이 쉽다 라이팅을 위한 계산이 “완전한” O(1) 복잡도를 가진다 .

오브젝트의 개수와 상관없다 Lighting 계산의 부하가 Scene 의 복잡도에 독립적이다 .

수많은 작은 동적 라이팅 사용이 가능하다

Killzone 2’s G-Buffer Layout (courtesy of Michal Valient)

Page 6: Light in screen_space(Light Pre Pass)

Deferred Shading MRT 를 이용한 랜더링 (Shader 3.0)

Depth BufferMotion Vec

DeferredLighting

Forward Rendering

Specular Normals Albedo /Shadow

Page 7: Light in screen_space(Light Pre Pass)

Deferred Shading 단점 투명 객체를 처리 못함 G-Buffer 안에 Material Property 들을 저장

G-Buffer 의 공간은 매우 제한적 ( 최대 4 장 ) 모든 Material 들에 대해서 아주 유사한 Lighting

공식이 사용되는 것을 요구 RenderTarget 4 장사용으로 메모리양이 큼 Forward Rendering 처럼 frame buffer 에 직접

렌더링할 때 자동으로 받는 하드웨어 anti-aliasing 이 불가능

Page 8: Light in screen_space(Light Pre Pass)

Light Pre Pass

Page 9: Light in screen_space(Light Pre Pass)

Light Pre-Pass

MRT 의 지원이 없어도 구현이 가능 Shader 2.0 환경에서 구현가능 ( 크게 의미는 없음 )

기본적으로 2Pass 로 랜더링을 이용하기 때문에 하드웨어 MSAA 를 지원 반투명 오브젝트는 2Pass 때 랜더링

Render Target 는 한장만 사용 Deferred Shading 과 비교할때 메모리양이 적음

Material 구현에 관하여 더 유연성를 제공 2Pass 때 처리

Page 10: Light in screen_space(Light Pre Pass)

Light Pre-Pass

Depth Buffer

Light Buffer

Forward Rendering

투명 객체Normals

Forward Rendering

1Pass

2Pass

Page 11: Light in screen_space(Light Pre Pass)

Light Pre-Pass 단점

Deferred Shading 의 경우 , 랜더는 최저 1 회로 끝 MRT 를 사용해 G-Buffer 에 랜더

Light Pre-Pass 는 기본적으로 2Pass 랜더 여러 개의 light 에 대해서 specular 항을 계산할 때의

문제점 (GameDev.net) Specular 값을 텍스쳐 한장으로 담아야 하기 때문에…

Page 12: Light in screen_space(Light Pre Pass)

Light Pre-Pass 적용 사례

S.T.A.L.K.E.R: Clear Skies

Page 13: Light in screen_space(Light Pre Pass)

Light Pre-Pass 적용 사례

BlurTM in-game screen-shot

Page 14: Light in screen_space(Light Pre Pass)

Light Pre-Pass 적용 사례

UnchartedTM in-game screenshot

Page 15: Light in screen_space(Light Pre Pass)

Light Pre Pass 구현 방법

Page 16: Light in screen_space(Light Pre Pass)

G Buffer (1Pass) Depth + Normal 추출 NORMAL 압축하여 뽑음

Normal 압축함으로 퀄리티 향상도 할 수 있음 RG : normal B : Depth A : Alpha Test

A16FR16FG16FB16 포멧 사용

Page 17: Light in screen_space(Light Pre Pass)

G Buffer (1Pass)

Gbuffer_VS { float4 position= float4( vertex.position , 1.0f ); Out.PosClip = mul(position, WORLDVIEWPROJ); Out.PosView = mul(position, WORLDVIEW);

float3 N = vertex.normal; float3 T = vertex.tangent.xyz; float3 B = cross(N,T) * vertex.tangent.w;

Out.TangentToView1 = mul( T, (float3x3)WORLDVIEW ); Out.TangentToView2 = mul( B, (float3x3)WORLDVIEW ); Out.TangentToView3 = mul( N, (float3x3)WORLDVIEW );}

Page 18: Light in screen_space(Light Pre Pass)

G Buffer (1Pass)

Gbuffer_PS{ float4 texcolor = tex2D( diffuseSampler , Input.TexCoords.xy ); float depth = Input.PosView.z / CAMERAFAR; float3 tangentSpaceNormal.xyz = tex2D( bumpSampler, Input.TexCoords.xy ).xyz * 2 - 1; float3x3mtxRot; mtxRot[0] = normalize( Input.TangentToView1 ); mtxRot[1] = normalize( Input.TangentToView2 ); mtxRot[2] = normalize( Input.TangentToView3 ); tangentSpaceNormal = normalize( mul( tangentSpaceNormal, mtxRot ) ); float4 packColor = PackDepthNormal(depth, tangentSpaceNormal); packColor.a = texcolor.a; return packColor;}

Page 19: Light in screen_space(Light Pre Pass)

Compact Normal Storage store X&Y, reconstruct Z

half4 encode (half3 n, float3 view) { return half4(n.xy*0.5+0.5,0,0); } half3 decode (half2 enc, float3 view) { half3 n; n.xy = enc*2-1; n.z = sqrt(1-dot(n.xy, n.xy)); return n; }

Compact Normal Storage for small G-Buffers http://aras-p.info/texts/CompactNormalStorage.html

Page 20: Light in screen_space(Light Pre Pass)

Compact Normal Storage Spheremap Transform

half2 encode (half3 n, float3 view) { half f = sqrt(8*n.z+8); return n.xy / f + 0.5; } half3 decode (half4 enc, float3 view) { half2 fenc = enc*4-2; half f = dot(fenc,fenc); half g = sqrt(1-f/4); half3 n; n.xy = fenc*g; n.z = 1-f/2; return n; }

Compact Normal Storage for small G-Buffers http://aras-p.info/texts/CompactNormalStorage.html

Page 21: Light in screen_space(Light Pre Pass)

Gbuffer(Depth)

Page 22: Light in screen_space(Light Pre Pass)

Gbuffer(Normal)

Page 23: Light in screen_space(Light Pre Pass)

Light Buffer Pass

Screen Space 에서 Gbuffer 을 이용하여 Light 를 계산 Light 계산시 Light 방향을 ViewSpace 로 변환하여 계산 Depth 로 위치를 뽑아서 Speculer 을 계산

Point Light 도 계산함 그림자도 Light 계산시 같이 할 수 있음 A16FR16FG16FB16F 포멧으로 설정Light buffer layoutR : LightColor.r * N.L * AttG : LightColor.g * N.L * AttB : LightColor.b * N.L * AttA : R.V^n * N.L * Att (Speculer)

Page 24: Light in screen_space(Light Pre Pass)

Light Buffer Pass 라이트버퍼 계산시 머트리얼 계산법

미리 계산해 놓으면 2Pass 때 빠르게 랜더링 할수 있음 머트리얼을 미리 계산할시 랜더타겟 한장이 더 필요

Page 25: Light in screen_space(Light Pre Pass)

Light Buffer Pass

CryEngine 3

Speculer Color 있음 Speculer Color 없음

Page 26: Light in screen_space(Light Pre Pass)

깊이 버퍼로부터 위치 계산• 픽셀의 실제 위치를 얻어낼 시 depth buffer 를 이용하여 만듬• 픽셀의 카메라 스페이스 상 위치를 얻어오는 일반적인 방법은 Inverse

Projection matrix 를 곱해주는 것 Depth 저장시 WVP 변환 결과의 z/w 값을 기입 하는 것이 아니고

WV 변환 결과의 Z 만 저장 하여 Linear 한 것으로 만들어 줌 floating 포맷이 아니라면 Zfar 로 나누면 될 듯

VS 에 프러스텀의 정보를 넘겨줌 좌상 , 우상 , 좌하 , 우하의 far clip 방향 ray

PS 에서는 해당 좌표에 받은 ray( 보간 되어 옴 ) 정보를 기반으로 깊이와 곱하여 최종 위치를 구함

SSAO , Motion blur(depth based), DOFFrustumCorner = Vector3(0,0,Far)FrustumCorner.y = tan( FOV / 2 ) * FarFrustumCorner.x = FrustumCorner.y * As-pect

Page 27: Light in screen_space(Light Pre Pass)

pos_vs { Out.Position = Input.Position; Out.TexCoords = Input.TexCoords.xy; Out.View = float3(FRUSTUMCORNER.x * Input.Position.x,

FRUSTUMCORNER.y * Input.Position.y, FRUSTUMCORNER.z);}

directional_ps { float fvDepth; float3 fvViewSpaceNormal; UnpackDepthNormal( normalDepthSampler , In.TexCoords, fvDepth, fvViewSpaceNormal );

float3 fvViewSpacePos = fvDepth * In.View;

float diffuseLight = saturate( dot( fvViewSpaceNormal, DIRLIGHT) + AMBIENT; float3 eyeVec = -normalize( fvViewSpacePos ); float3 halfVec = normalize( eyeVec + DIRLIGHT ); float specular = pow( saturate( dot( fvViewSpaceNormal, halfVec) SHININESS ) return float4(diffuseLight , specular * NdotL); }

Light Buffer Pass

Page 28: Light in screen_space(Light Pre Pass)

Light Buffer( Light )

Page 29: Light in screen_space(Light Pre Pass)

Light Buffer( Speculer )

Page 30: Light in screen_space(Light Pre Pass)

라이트의 퀄리티를 높혀보자 ( 팁 ?)

Ambient Cube ( Valve’s ) 구현이 매우 간단함 적은 계산량으로 간접 조명을 보여줄 수 있음 각 점마다 6 개의 irradiance 값을 미리 계산해서 배치

디자이너가 Cube 의 6 개 색을 미리 지정 주인공 캐릭터들은 가장 가까운 점을 얻어와서

간접조명 (indirect illumination) 으로 사용 Shading in Valve's Source Engine 참조

float3 AmbientLight( const float3 worldNormal ){float3 nSquared = worldNormal * worldNormal;int3 isNegative = ( worldNormal < 0.0 );float3 linearColor;linearColor = nSquared.x * cAmbientCube[isNegative.x] +

nSquared.y * cAmbientCube[isNegative.y+2] +

nSquared.z * cAmbientCube[isNegative.z+4];return linearColor;}

Page 31: Light in screen_space(Light Pre Pass)

Light Buffer( Light + AmbientCube)

Page 32: Light in screen_space(Light Pre Pass)

Light Buffer( Light )

Ambient 만 사용

Ambient Cube 사용

Page 33: Light in screen_space(Light Pre Pass)

2Pass Pass 때 미리 찍어둔 ZBuffer 를 이용하여

ZCull(EalryZ) 을 사용하여 랜더 z-culling 은 깊이에 기반하여 미리 픽셀을 배제하는 것 Render depth only, 1Pass

ZWRITEENABLE = TRUE, ZFUNC = LESSEQUAL Render with full shaders, 2Pass

Early-Z (and Z-Cull) ZWRITEENABLE = FALSE, ZFUNC = EQUAL

Diffuse 와 누적된 라이트텍스쳐를 계산 Diffuse * LightBuffer

투명 객체 랜더

Page 34: Light in screen_space(Light Pre Pass)

Light Pre Pass 정리 Gbuffer Pass ( 1Pass )

불투명 객체들에 대해서 , view normal 과 view depth 를 저장

Light Pass Accumulate Light Info

2Pass Diffuse * LightBuffer

투명 객체 랜더링

Page 35: Light in screen_space(Light Pre Pass)

Light-Pre-Pass Final

Page 36: Light in screen_space(Light Pre Pass)

정리

수많은 동적 라이팅을 화면상의 오브젝트의 개수와 관계없이 상수시간에 처리가 가능함

이론상 무한개의 동적 라이팅 사용 가능 어두운 실내나 , 어두운 배경에 실시간 라이팅이 많은 경우

최적의 해결 방법 현재의 그래픽 카드에서는 당연히 지원됨유명 상용 엔진에서는

기본적으로 지원됨 직접 구현 해도 , 개념이 어렵지 않고 , 관리가 쉬움 셀프 셰도우등 그림자 기법이 용이함 포스트 프로세싱 (DOF, SSAO, HDR 등 ) 을 사용시

G-Buffer 재사용 가능함 콘솔게임은 이미 많은 게임들이 사용되고 있음 .

Page 37: Light in screen_space(Light Pre Pass)

References[Hargreaves] Shawn Hargreaves, “Deferred Shading”, http://www.talula.demon.co.uk/DeferredShading.pdf

[Lobanchikov] Igor A. Lobanchikov, “ GSC Game World‘s S.T.A.L.K.E.R : Clear Sky – a showcase for Direct3D 10.0/1”, http://developer.amd.com/gpu_assets/01GDC09AD3DDStalkerClearSky210309.ppt

[Mittring] Martin Mittring, “A bit more Deferred – Cry Engine 3”, http://www.slideshare.net/guest11b095/a-bit-more-deferred-cry-engine3

[Lee] Mark Lee, “Resistance 2 Prelighting”, http://www.insomniacgames.com/tech/articles/0409/files/GDC09_Lee_Prelighting.pdf

[Lengyel] Eric Lengyel, “Advanced Light and Shadow Culling Methods”, http://www.terathon.com/lengyel/#slides

[Placeres] Frank Puig Placeres, “Overcoming Deferred Shading Drawbacks,” pp. 115 – 130, ShaderX5

[Shishkovtsov] Oles Shishkovtsov, “Making some use out of hardware multisampling”; http://oles-rants.blogspot.com/2008/08/making-some-use-out-of-hardware.html

[Swoboda] Matt Swoboda, “Deferred Lighting and Post Processing on PLAYSTATION®3, http://research.scee.net/presentations

[Tovey] Steven J. Tovey, Stephen McAuley, “Parallelized Light Pre-Pass Rendering withthe Cell Broadband EngineTM”, to appear in GPU Pro [Thibieroz04] Nick Thibieroz, “Deferred Shading with Multiple-Render-Targets,” pp. 251 – 269, ShaderX2

[Thibieroz] Nick Thibieroz, “Deferred Shading with Multisampling Anti-Aliasing in DirectX 10” , ShaderX7

[Valient] Michael Valient, “Deferred Rendering in Killzone 2,” www.guerillagames.com/publications/dr_kz2_rsx_dev07.pdf

[Wolfgang Engel] Wolfgang Engel, Light Pre-Pass Deferred Lighting: Latest Development- August 3rd, 2009

[ 김대일 ] 웹젠 Rendering C9 kgc2009

[ 이창희 ] Kasa Light-Pre-Pass 2009-07-04

[ 박민근 ] 네이버 초중급 게임 개발자 스터디 [ 데브루키 ] Deferred Shading ( 지연 세이딩 )

[ 오즈라엘님 블로그 ] http://ozlael.egloos.com/2374651

[ 오즈라엘님 블로그 ] http://ozlael.egloos.com/2876211

Z-culling http://codevania.springnote.com/pages/3936893.xhtml

Compact Normal Storage for small G-Buffers http://aras-p.info/texts/CompactNormalStorage.html


Recommended