SlideShare a Scribd company logo
1 of 15
ShaderX7 2.4.Fast Skin Shading John Hable, George Borshukov, Jim Hejl Shader Study (http://cafe.naver.com/shader) 임용균
Introduction 많은 게임들이 일반적인 라이팅 모델을 피부에도 적용함으로 플라스틱 같은 느낌이 나 피부 같은 느낌이 없다. 피부는 판지와 같은 pure diffuse surface와는 매우 다르다. 근본적인 차이는 피부 안에서 빛들의 반사가 매우 다름에 있다. 피부는 투명도의 단계가 다른 여러 layer로 구성 되어 있다. 피부 밑에서 빛이 어떻게 통과하는지에 대한 빠른 시뮬레이션의 구현 (PS3, Xbox 360 수준을 목표)
Background GPU Gems 3 [d’EonGPUGems07] Subsurface scattering Step1 : 빛이 피부에 닿음 diffuse light를 라이트맵에 렌더링 Step2 : 빛이 피부 아래에서 반사 됨  라이트맵을블러링함으로 시뮬레이션 Step3 : 빛이 피부 밖으로 빠져나감. 카메라에 의해 보여짐 블러링된 빛을 diffuse map에 multiplying함으로 시뮬레이션
Diffuse 피부의 한 점의 diffuse를 계산하기 위해서는 그 점 주변의 들어오는 빛의 intensity를 알아야 한다. diffusion dipole로 거의 해결되었다. [Donner05] 빛과 점의 거리에 따라 red, green, blue의 intensity가 다른 커브를 발견. diffusion dipole을 blur들의 합으로 분해할 수 있다. real-time으로 실행할 수 있다. 5번의 7x7 gaussian blur가 1번의 50x50 gaussian blur보다 빠르다. blur 회수를 조절하여 다양한 피부 타입을나타내는것이 가능하다.
Our Contributions blur의 samping pattern을 변경함으로 additional error를 많이 줄일 수 있었다. d’Eon과 Leubke의 테크닉을 시뮬레이션 하지만 좀더 적은 tap을 이용한다. (~12 samples) 두개의“링”을 이용하여 블러를 시뮬레이션 함으로 좋은 결과를 얻었다. 각각의 링을 6섹션으로 나눔 (총 12섹션) 섹션마다 jittered sample을 한다. sample에 맞는 weight를 적용한다.
Our Contributions float2 blurJitteredSamples[13] = { { 0.000000,0.000000 }, { 1.633992, 0.036795 }, { 0.177801, 1.717593 }, { -0.194906, 0.091094 }, { -0.239737, -0.220217 }, { -0.003530, -0.118219 }, { 1.320107, -0.181542 }, { 5.970690, 0.253378 }, { -1.089250, 4.958349 }, { -4.015465, 4.156699 }, { -4.063099, -4.110150 }, { -0.638605, -6.297663 }, { 2.542348, -3.245901 }, }; float3 blurJitteredWeights[13] = { { 0.220441, 0.437000, 0.635000 }, { 0.076356, 0.064487, 0.039097 }, { 0.116515, 0.103222, 0.064912 }, { 0.064844, 0.086388, 0.062272 }, { 0.131798, 0.151695, 0.103676 }, { 0.025690, 0.042728, 0.033003 }, { 0.048593, 0.064740, 0.046131 }, { 0.048092, 0.003042, 0.000400 }, { 0.048845, 0.005406, 0.001222 }, { 0.051322, 0.006034, 0.001420 }, { 0.061428, 0.009152, 0.002511 }, { 0.030936, 0.002868, 0.000652 }, { 0.073580, 0.023239, 0.009703 }, };
Our Contributions blur pass float3 totalColor = 0; float2 strectch = tex2D(StretchTextureBlurred, uv.xy).rg; float shadow = tex2D(LightMap, uv.xy).a; for (inti=0; i<=12; i++) totalColor += SubsurfaceJitterSampler(uv.xy, stretch, i);
Our Contributions High-Z Light map 렌더링패스에서 depth를 기록한다. depth = dot(N, V) * 0.5 + 0.5 High-Z를 사용하여 오직 앞면의폴리곤에blur를 적용한다. 위의 공식에서는 depth가 0.5이상인 픽셀만 blur를 적용하면 된다. Texture Size Light mapblur 텍스쳐는 원래의 Diffuse 	texture보다 작은것을 이용한다. (512x512 fp16RGBA buffer) ,[object Object]
Capture 장비일 경우 자동 Blur 현상
최종 합성 단계에서 diffuse map과의 합성,[object Object]
Specular 피부는 실제적으로 매우 광택이 있다. Phong모델은 적합하지 않음 하나의 퐁 모델이 나타내는 범위로는 비슷하게 표현이 불가능 적합한 Specular모델은? 여러 개의 범위를 나타낼수 있는 모델이어야 한다.  built-in fresnel term이 있어야 한다. grazing angle에서 specular highlight가 더 밝아야 한다. Kelemen-Szirmay-Kalos [Kelemen01] 모델을 사용 그러나 비용이 비싸다.
Variation Across the Face 얼굴의 모든 부분에 하나의 라이팅 모델을 적용하는 것은 맞지 않다. 특정 부분은 다른 부분보다 더 밝다. 부위마다 subsurface scattering 효과도 다르다. Specular Map을 추가하여 Specular를 제어 한다. 드라마틱하게 향상되지는 않지만 추천하는 방법 Subsurfacy Map을 추가하여 subsurface scattering을 제어 크게 향상되지는 않지만 다른 느낌을 준다. 다양한 느낌을 원한다면 이용 할 만 하다.  	(older dark-skinned male VS young white female)
Final Shader float diffuse = saturate(dot(lightVec, normal)); float finalShadow = tex2D(LightmapCombineBlur, uv.xy).w; float3 readModelColor = pow(tex2D(HeadDiffuse, uv.xy), 2.2); float4 outColor = float4(0, 0, 0, 1); float3 linearLightColor = pow(lightColor, 2.2) * lightBrightness; float3 diffusePoint = Kd * linearLightColor * diffuse * finalShadow; float lightmapAmount = tex2D(StretchTexture, uv.xy).b; float3 diffuseBlurred = Kd * tex2D(LightmapCombinedBllur, float2(uv.x, uv.y)).rgb; diffuseColor = blurJitteredWeights[0]  diffusePoint +  		lerp((float3(1, 1, 1) – blurJitteredWeights[0]) * diffusePoint, diffuseBlurred, lightmapAmount); specular = KelemenSzirmauKalosSpec(normalize(viewVec), normal, lightVec,  		eccentricity, rolloff, weight); outColor.rgb = Ao * Ka * realModelColor + (diffuseColor * realModelColor + kS * linearLightColor * specular * finalShadow);
Data Preparation 실사적인 결과물을 얻기 위해서는 스캔 데이터를 이용하는 것을 추천 데모에 사용된 머리는 XYZRGB로 스캔되었음 Gamma correction이 핵심적으로 필요함 적절한 gamma correction이 diffuse map들에 적용되어야 한다. Normal map이 중요함 실제 얼굴의 표면은 매우 울퉁불퉁하다. Subsurface scattering은 모습을 부드럽게 한다.

More Related Content

Similar to Fast skin shading

Reflective Shadow Maps
Reflective Shadow MapsReflective Shadow Maps
Reflective Shadow MapsBongseok Cho
 
Screen space reflection
Screen space reflectionScreen space reflection
Screen space reflectionBongseok Cho
 
6강 light shadow 기초
6강 light shadow 기초6강 light shadow 기초
6강 light shadow 기초JP Jung
 
6강 light shadow 기초
6강 light shadow 기초6강 light shadow 기초
6강 light shadow 기초JP Jung
 
6강 light shadow 기초
6강 light shadow 기초6강 light shadow 기초
6강 light shadow 기초JP Jung
 
Depth buffershadow
Depth buffershadowDepth buffershadow
Depth buffershadowMoonLightMS
 
[1023 박민수] 깊이_버퍼_그림자_1
[1023 박민수] 깊이_버퍼_그림자_1[1023 박민수] 깊이_버퍼_그림자_1
[1023 박민수] 깊이_버퍼_그림자_1MoonLightMS
 
[1023 박민수] 깊이_버퍼_그림자
[1023 박민수] 깊이_버퍼_그림자[1023 박민수] 깊이_버퍼_그림자
[1023 박민수] 깊이_버퍼_그림자MoonLightMS
 

Similar to Fast skin shading (8)

Reflective Shadow Maps
Reflective Shadow MapsReflective Shadow Maps
Reflective Shadow Maps
 
Screen space reflection
Screen space reflectionScreen space reflection
Screen space reflection
 
6강 light shadow 기초
6강 light shadow 기초6강 light shadow 기초
6강 light shadow 기초
 
6강 light shadow 기초
6강 light shadow 기초6강 light shadow 기초
6강 light shadow 기초
 
6강 light shadow 기초
6강 light shadow 기초6강 light shadow 기초
6강 light shadow 기초
 
Depth buffershadow
Depth buffershadowDepth buffershadow
Depth buffershadow
 
[1023 박민수] 깊이_버퍼_그림자_1
[1023 박민수] 깊이_버퍼_그림자_1[1023 박민수] 깊이_버퍼_그림자_1
[1023 박민수] 깊이_버퍼_그림자_1
 
[1023 박민수] 깊이_버퍼_그림자
[1023 박민수] 깊이_버퍼_그림자[1023 박민수] 깊이_버퍼_그림자
[1023 박민수] 깊이_버퍼_그림자
 

More from yong gyun im

Rendering realistic Ice objects
Rendering realistic Ice objectsRendering realistic Ice objects
Rendering realistic Ice objectsyong gyun im
 
Rendering realistic Ice objects
Rendering realistic Ice objectsRendering realistic Ice objects
Rendering realistic Ice objectsyong gyun im
 
Gpu Gems 1 Chapter 6
Gpu Gems 1 Chapter 6Gpu Gems 1 Chapter 6
Gpu Gems 1 Chapter 6yong gyun im
 
Shaderstudy Motion Blur
Shaderstudy Motion BlurShaderstudy Motion Blur
Shaderstudy Motion Bluryong gyun im
 

More from yong gyun im (7)

Rendering realistic Ice objects
Rendering realistic Ice objectsRendering realistic Ice objects
Rendering realistic Ice objects
 
Rendering realistic Ice objects
Rendering realistic Ice objectsRendering realistic Ice objects
Rendering realistic Ice objects
 
Fur rendering
Fur renderingFur rendering
Fur rendering
 
Sumie rendering
Sumie renderingSumie rendering
Sumie rendering
 
Inferred Lighting
Inferred LightingInferred Lighting
Inferred Lighting
 
Gpu Gems 1 Chapter 6
Gpu Gems 1 Chapter 6Gpu Gems 1 Chapter 6
Gpu Gems 1 Chapter 6
 
Shaderstudy Motion Blur
Shaderstudy Motion BlurShaderstudy Motion Blur
Shaderstudy Motion Blur
 

Fast skin shading

  • 1. ShaderX7 2.4.Fast Skin Shading John Hable, George Borshukov, Jim Hejl Shader Study (http://cafe.naver.com/shader) 임용균
  • 2. Introduction 많은 게임들이 일반적인 라이팅 모델을 피부에도 적용함으로 플라스틱 같은 느낌이 나 피부 같은 느낌이 없다. 피부는 판지와 같은 pure diffuse surface와는 매우 다르다. 근본적인 차이는 피부 안에서 빛들의 반사가 매우 다름에 있다. 피부는 투명도의 단계가 다른 여러 layer로 구성 되어 있다. 피부 밑에서 빛이 어떻게 통과하는지에 대한 빠른 시뮬레이션의 구현 (PS3, Xbox 360 수준을 목표)
  • 3. Background GPU Gems 3 [d’EonGPUGems07] Subsurface scattering Step1 : 빛이 피부에 닿음 diffuse light를 라이트맵에 렌더링 Step2 : 빛이 피부 아래에서 반사 됨 라이트맵을블러링함으로 시뮬레이션 Step3 : 빛이 피부 밖으로 빠져나감. 카메라에 의해 보여짐 블러링된 빛을 diffuse map에 multiplying함으로 시뮬레이션
  • 4. Diffuse 피부의 한 점의 diffuse를 계산하기 위해서는 그 점 주변의 들어오는 빛의 intensity를 알아야 한다. diffusion dipole로 거의 해결되었다. [Donner05] 빛과 점의 거리에 따라 red, green, blue의 intensity가 다른 커브를 발견. diffusion dipole을 blur들의 합으로 분해할 수 있다. real-time으로 실행할 수 있다. 5번의 7x7 gaussian blur가 1번의 50x50 gaussian blur보다 빠르다. blur 회수를 조절하여 다양한 피부 타입을나타내는것이 가능하다.
  • 5.
  • 6. Our Contributions blur의 samping pattern을 변경함으로 additional error를 많이 줄일 수 있었다. d’Eon과 Leubke의 테크닉을 시뮬레이션 하지만 좀더 적은 tap을 이용한다. (~12 samples) 두개의“링”을 이용하여 블러를 시뮬레이션 함으로 좋은 결과를 얻었다. 각각의 링을 6섹션으로 나눔 (총 12섹션) 섹션마다 jittered sample을 한다. sample에 맞는 weight를 적용한다.
  • 7. Our Contributions float2 blurJitteredSamples[13] = { { 0.000000,0.000000 }, { 1.633992, 0.036795 }, { 0.177801, 1.717593 }, { -0.194906, 0.091094 }, { -0.239737, -0.220217 }, { -0.003530, -0.118219 }, { 1.320107, -0.181542 }, { 5.970690, 0.253378 }, { -1.089250, 4.958349 }, { -4.015465, 4.156699 }, { -4.063099, -4.110150 }, { -0.638605, -6.297663 }, { 2.542348, -3.245901 }, }; float3 blurJitteredWeights[13] = { { 0.220441, 0.437000, 0.635000 }, { 0.076356, 0.064487, 0.039097 }, { 0.116515, 0.103222, 0.064912 }, { 0.064844, 0.086388, 0.062272 }, { 0.131798, 0.151695, 0.103676 }, { 0.025690, 0.042728, 0.033003 }, { 0.048593, 0.064740, 0.046131 }, { 0.048092, 0.003042, 0.000400 }, { 0.048845, 0.005406, 0.001222 }, { 0.051322, 0.006034, 0.001420 }, { 0.061428, 0.009152, 0.002511 }, { 0.030936, 0.002868, 0.000652 }, { 0.073580, 0.023239, 0.009703 }, };
  • 8. Our Contributions blur pass float3 totalColor = 0; float2 strectch = tex2D(StretchTextureBlurred, uv.xy).rg; float shadow = tex2D(LightMap, uv.xy).a; for (inti=0; i<=12; i++) totalColor += SubsurfaceJitterSampler(uv.xy, stretch, i);
  • 9.
  • 10. Capture 장비일 경우 자동 Blur 현상
  • 11.
  • 12. Specular 피부는 실제적으로 매우 광택이 있다. Phong모델은 적합하지 않음 하나의 퐁 모델이 나타내는 범위로는 비슷하게 표현이 불가능 적합한 Specular모델은? 여러 개의 범위를 나타낼수 있는 모델이어야 한다. built-in fresnel term이 있어야 한다. grazing angle에서 specular highlight가 더 밝아야 한다. Kelemen-Szirmay-Kalos [Kelemen01] 모델을 사용 그러나 비용이 비싸다.
  • 13. Variation Across the Face 얼굴의 모든 부분에 하나의 라이팅 모델을 적용하는 것은 맞지 않다. 특정 부분은 다른 부분보다 더 밝다. 부위마다 subsurface scattering 효과도 다르다. Specular Map을 추가하여 Specular를 제어 한다. 드라마틱하게 향상되지는 않지만 추천하는 방법 Subsurfacy Map을 추가하여 subsurface scattering을 제어 크게 향상되지는 않지만 다른 느낌을 준다. 다양한 느낌을 원한다면 이용 할 만 하다. (older dark-skinned male VS young white female)
  • 14. Final Shader float diffuse = saturate(dot(lightVec, normal)); float finalShadow = tex2D(LightmapCombineBlur, uv.xy).w; float3 readModelColor = pow(tex2D(HeadDiffuse, uv.xy), 2.2); float4 outColor = float4(0, 0, 0, 1); float3 linearLightColor = pow(lightColor, 2.2) * lightBrightness; float3 diffusePoint = Kd * linearLightColor * diffuse * finalShadow; float lightmapAmount = tex2D(StretchTexture, uv.xy).b; float3 diffuseBlurred = Kd * tex2D(LightmapCombinedBllur, float2(uv.x, uv.y)).rgb; diffuseColor = blurJitteredWeights[0] diffusePoint + lerp((float3(1, 1, 1) – blurJitteredWeights[0]) * diffusePoint, diffuseBlurred, lightmapAmount); specular = KelemenSzirmauKalosSpec(normalize(viewVec), normal, lightVec, eccentricity, rolloff, weight); outColor.rgb = Ao * Ka * realModelColor + (diffuseColor * realModelColor + kS * linearLightColor * specular * finalShadow);
  • 15. Data Preparation 실사적인 결과물을 얻기 위해서는 스캔 데이터를 이용하는 것을 추천 데모에 사용된 머리는 XYZRGB로 스캔되었음 Gamma correction이 핵심적으로 필요함 적절한 gamma correction이 diffuse map들에 적용되어야 한다. Normal map이 중요함 실제 얼굴의 표면은 매우 울퉁불퉁하다. Subsurface scattering은 모습을 부드럽게 한다.
  • 16. Conclusion 기존의 방법들(Doug Jones Demo)과 비슷한 결과물을 내면서 속도는 10배 정도 빠르다. Xbox360에서 512x512 buffer blur step을 0.45ms에 실행한다. Doug Jones Demo에 비해 품질이 떨어지는 부분이 있다. “fleshiness” 적은 커널을 사용함으로 red channel의 넓은 blur를 정확히 표현하지 못한다. 미묘한 부분의 생략 Stretching에 약간의 문제가 있음 low stretch부분이 high stretch부분과 만나는 지점 알아차릴만한 blurring artifacts가 발생함 귀 주변과 같은 부분