Lighting In Screen Space(Light Pre-Pass)
이민웅
차례 많은 광원을 그리는 방법들
Deferred Shading Light Pre-Pass 소개 Light Pre-Pass 구현방법
GBuffer Light Buffer
정리 질문
많은 광원을 그리는 방법들 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
Z Pre Pass Rendering 존카멕이 처음 개발 Doom3 적용 Depth 만을 가지고 Light 계산
Deferred Shading 굉장히 배치가 간단해지고 , 엔진에서 관리가 쉽다
일반적인 그림자 테크닉들과 통합이 쉽다 라이팅을 위한 계산이 “완전한” O(1) 복잡도를 가진다 .
오브젝트의 개수와 상관없다 Lighting 계산의 부하가 Scene 의 복잡도에 독립적이다 .
수많은 작은 동적 라이팅 사용이 가능하다
Killzone 2’s G-Buffer Layout (courtesy of Michal Valient)
Deferred Shading MRT 를 이용한 랜더링 (Shader 3.0)
Depth BufferMotion Vec
DeferredLighting
Forward Rendering
Specular Normals Albedo /Shadow
Deferred Shading 단점 투명 객체를 처리 못함 G-Buffer 안에 Material Property 들을 저장
G-Buffer 의 공간은 매우 제한적 ( 최대 4 장 ) 모든 Material 들에 대해서 아주 유사한 Lighting
공식이 사용되는 것을 요구 RenderTarget 4 장사용으로 메모리양이 큼 Forward Rendering 처럼 frame buffer 에 직접
렌더링할 때 자동으로 받는 하드웨어 anti-aliasing 이 불가능
Light Pre Pass
Light Pre-Pass
MRT 의 지원이 없어도 구현이 가능 Shader 2.0 환경에서 구현가능 ( 크게 의미는 없음 )
기본적으로 2Pass 로 랜더링을 이용하기 때문에 하드웨어 MSAA 를 지원 반투명 오브젝트는 2Pass 때 랜더링
Render Target 는 한장만 사용 Deferred Shading 과 비교할때 메모리양이 적음
Material 구현에 관하여 더 유연성를 제공 2Pass 때 처리
Light Pre-Pass
Depth Buffer
Light Buffer
Forward Rendering
투명 객체Normals
Forward Rendering
1Pass
2Pass
Light Pre-Pass 단점
Deferred Shading 의 경우 , 랜더는 최저 1 회로 끝 MRT 를 사용해 G-Buffer 에 랜더
Light Pre-Pass 는 기본적으로 2Pass 랜더 여러 개의 light 에 대해서 specular 항을 계산할 때의
문제점 (GameDev.net) Specular 값을 텍스쳐 한장으로 담아야 하기 때문에…
Light Pre-Pass 적용 사례
S.T.A.L.K.E.R: Clear Skies
Light Pre-Pass 적용 사례
BlurTM in-game screen-shot
Light Pre-Pass 적용 사례
UnchartedTM in-game screenshot
Light Pre Pass 구현 방법
G Buffer (1Pass) Depth + Normal 추출 NORMAL 압축하여 뽑음
Normal 압축함으로 퀄리티 향상도 할 수 있음 RG : normal B : Depth A : Alpha Test
A16FR16FG16FB16 포멧 사용
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 );}
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;}
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
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
Gbuffer(Depth)
Gbuffer(Normal)
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)
Light Buffer Pass 라이트버퍼 계산시 머트리얼 계산법
미리 계산해 놓으면 2Pass 때 빠르게 랜더링 할수 있음 머트리얼을 미리 계산할시 랜더타겟 한장이 더 필요
Light Buffer Pass
CryEngine 3
Speculer Color 있음 Speculer Color 없음
깊이 버퍼로부터 위치 계산• 픽셀의 실제 위치를 얻어낼 시 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
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
Light Buffer( Light )
Light Buffer( Speculer )
라이트의 퀄리티를 높혀보자 ( 팁 ?)
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;}
Light Buffer( Light + AmbientCube)
Light Buffer( Light )
Ambient 만 사용
Ambient Cube 사용
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
투명 객체 랜더
Light Pre Pass 정리 Gbuffer Pass ( 1Pass )
불투명 객체들에 대해서 , view normal 과 view depth 를 저장
Light Pass Accumulate Light Info
2Pass Diffuse * LightBuffer
투명 객체 랜더링
Light-Pre-Pass Final
정리
수많은 동적 라이팅을 화면상의 오브젝트의 개수와 관계없이 상수시간에 처리가 가능함
이론상 무한개의 동적 라이팅 사용 가능 어두운 실내나 , 어두운 배경에 실시간 라이팅이 많은 경우
최적의 해결 방법 현재의 그래픽 카드에서는 당연히 지원됨유명 상용 엔진에서는
기본적으로 지원됨 직접 구현 해도 , 개념이 어렵지 않고 , 관리가 쉬움 셀프 셰도우등 그림자 기법이 용이함 포스트 프로세싱 (DOF, SSAO, HDR 등 ) 을 사용시
G-Buffer 재사용 가능함 콘솔게임은 이미 많은 게임들이 사용되고 있음 .
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