video:
http://software.intel.com/en-us/videos/confetti-special-effects-demo-at-gdc-2011/
docs:
http://www.confettispecialfx.com/gdc-wrap-up
http://www.conffx.com/GDC2011.zip
瓦夫缸(wolfgang)原来是这个样子,太符合我心目中的技术宅男大叔的形象了,就冲这个形象,也要狂顶。
里面一共3篇文章。
sky render
每个部分的技术点:
sky light包含一系列reflect,scatering这么个东东。
offline cook进look up table(LUT),也就是一个texture。
cloud
在crytek07gdc那个文章:link
的基础上(volume property+rim lighting),加了imposter的使用,算是中规中矩。
lighting & shadowing
deferred lighting
wolfgang为intel的sandy bridge开发的graphic demo,技术点也还可以,可惜这次gdc遇到了epic,直接被无视了,gamedev竞争残酷啊。
使用的deferred lighting(light prepass),
geometry buffer : normal+specular, depth
calc lighting
then final result with color buffer.
light buffer是rgb存diffuse lighting结果,带lighting颜色,a存specular,无lighting颜色。
specular可以从diffuse lighting结果中,使用chromacity重建出lighting color。
point light shadow
使用cube map shadow,说比dual paraboloid shadow有"more even error distribution",但是这个代价有点大吧。
使用esm作为soft shadow方案
使用了shadow caching。
screen space material
其实也就是screen space subsurface scattering,也叫5s。
具体的代码给了,nice:
float4 SubSurfaceScatteringBlur( SamplerState bilinearFilter, SamplerState pointFilter, Texture2D colorTx, Texture2D depthTx, float2 dim, float2 uv, float width, float q, float near ) { float2 pixelSize = 1.0f / dim; ////// CALCULATE GRADIENT ////// float depth = depthTx.Sample( pointFilter, uv ); //hyperbolic depth float2 s = float2( 0.0f, 0.0f ); float2 step = float2( 0.0f, 0.0f ); //these variables are tweakables const float maxdd = 0.001f; const float correction = 800.0f; const float ssLevel = 20.0f; step.xy = ssLevel.xx * width.xx * pixelSize.xy; float2 gradient = min( abs( float2( ddx( depth ), ddy( depth ) ) ), maxdd.xx ); s.xy = step.xy / (depth.xx + gradient.xy * correction.xx ); float2 offset = s / SAMPLE_COUNT; ////// BLUR ////// float3 color = float3( 0.0f, 0.0f, 0.0f ); float3 totalWeight = 0.0f; float4 middle = colorTx.Sample( pointFilter, uv ); for( int i = 0; i < SAMPLE_COUNT;++i ) { float2 pos = uv + BLUR_JITTERED_SAMPLES[ i ] * offset; float4 sample = colorTx.Sample( bilinearFilter, pos ); float weight = sample.a; color += sample.rgb * weight.xxx * BLUR_JITTERED_WEIGHTS[ i ].xyz; totalWeight += weight.xxx * BLUR_JITTERED_WEIGHTS[ i ].xyz;; } return length(totalWeight) < 0.1f ? middle, float4( color / totalWeight, middle.a ); }