際際滷

際際滷Share a Scribd company logo
Volumetric Fog 1
Volumetric Fog
覈谿
1. Volumetric Fog
2. 蟲覦覯
3. 覲朱エれ
4. 磯覦鰢螻
a. 磯螻
i. Phase function
b. 覦螻
5. 磯
a. Beer-Lambert 覯豺
6. Fog 
7. 讌レ螳
a. Temporal reprojection
b. Tricubic texture sampling
8. 襷豺覃
9. Reference
Volumetric Fog
Volumetric Fog覓朱Μ蠍磯譟磯磯螻壱豌伎語螳襯狩蠍磯. 螳語觜覲企ろ誤襦語るゼ
豌危螳企ゼ磯給.
Volumetric FogSIGGRAPH 2014Ubisoft螳覦Volumetric fog: Unified, compute shader based solution to
atmospheric scattering 牛伎螳給. 願企轟襭襯手鍵覦朱Direct3D 11/12襦蟲蟆郁骸覓殊牛
Volumetric Fog蠍磯蓋瑚規覦覯螳螻碁Μ殊讌Volumetric Fog螳企至蟲伎讌危エ覲企襦蟆給
.
蟲覦覯
Volumetric Fogれ螻手襦蟲.
1. 豌伎覲朱エれ襯殊
2. 貉危語一企襯狩牛企骸襯れ螳磯覦鰢螻
Volumetric Fog 2
3. 豺企朱一蟇磯Μ磯ジ磯
4. SceneFog
危襦螳螻襯殊誤覲企襦蟆給.
覲朱エれ
螳ル┝覲朱エれ襯殊燕螳給. 覲朱エれ3D螻糾磯覦鰢覲企ゼロ一.
覦襭磯ゴ覃企骸襯れ蠍磯720p蠍一朱弰磯160x90x64(螳襦x碁x蟾) 轟160x90x128企壱襷血朱
16bit RGBA Float襯殊り.
160x90x128 蠍一覲朱エれ襯UAVSRV襦襦燕給. 覲朱エれ煙れれ
螻手給.
const std::array<uint32, 3>& frustumGridSize = Proxy()->FrustumGridSize();
agl::TextureTrait frustumVolumeTrait = {
.m_width = frustumGridSize[0], // 160
.m_height = frustumGridSize[1], // 90
.m_depth = frustumGridSize[2], // 128
.m_sampleCount = 1,
.m_sampleQuality = 0,
.m_mipLevels = 1,
.m_format = agl::ResourceFormat::R16G16B16A16_FLOAT,
.m_access = agl::ResourceAccessFlag::GpuRead | agl::ResourceAccessFlag::GpuWrite,
.m_bindType = agl::ResourceBindType::RandomAccess | agl::ResourceBindType::ShaderResource,
.m_miscFlag = agl::ResourceMisc::Texture3D
};
企蟆燕覲朱エれ螳豺企手概螳殊覲旧磯覦鰢覲企ゼロ壱れ蠍一曙
蠍磯覓語豺企手概螳蠏燕蟆覿蟆伎手蟾願崖伎襯殊螻牛蠍一z豢(豺企手覲企覦) 讌
覿襯朱磯ゴ襦覿. 覲朱エれid襯朱螻糾譬襦覲襯狩牛伎誤螻糾覿螻殊覲
蟆給.
/*
- input
id : 覲朱エ れ  id (x,y,z)
dims : 覲朱エ れ 蠍 (width, height, depth)
- output
 螻糾 譬
*/
float3 ConvertThreadIdToWorldPosition( uint3 id, uint3 dims )
{
// id -> ndc
float3 ndc = ConvertThreadIdToNdc( id, dims );
float depth = ConvertNdcZToDepth( ndc.z );
return ConvertToWorldPosition( ndc, depth );
}
襾殊覲朱エれidれ蠍磯ゼ語襦覦NDC(Normalized Device Coordinate) 螻糾朱覲蟆渚. 願骸企
覲ConvertThreadIdToNdcれ螻手給.
/*
- input
Volumetric Fog 3
id : 覲朱エ れ  id (x,y,z)
dims : 覲朱エ れ 蠍 (width, height, depth)
- output
Direct3D 殊 譬螻襯 磯ゴ覩襦 X,Y 螳 -1 ~ 1 Z螳 0 ~ 1 覯 NDC 螻糾 譬
*/
float3 ConvertThreadIdToNdc( uint3 id, uint3 dims )
{
float3 ndc = id;
ndc += 0.5f;
ndc *= float3( 2.f / dims.x, -2.f / dims.y, 1.f / dims.z );
ndc += float3( -1.f, 1.f, 0.f );
return ndc;
}
NDC 螻糾譬襯殊至覃Z譬螳牛伎覿襯朱磯朱豺企手概螳蟾願詞給. 願骸
ConvertNdcZToDepth企讌.
/*
- input
ndcZ : NDC 螻糾 Z譬
- global parameter
VolumetricFogParam.DepthPackExponent : 讌 覿 覲  讌
VolumetricFogParam.NearPlaneDist : Fog  蠏狩覃願讌 蟇磯Μ
VolumetricFogParam.FarPlaneDist : Fog  覃願讌 蟇磯Μ
- ouput
讌 覿襯 磯朱 豺企 螻糾 蟾
*/
float ConvertNdcZToDepth( float ndcZ )
{
float depthPackExponent = VolumetricFogParam.DepthPackExponent;
float nearPlaneDist = VolumetricFogParam.NearPlaneDist;
float farPlaneDist = VolumetricFogParam.FarPlaneDist;
return pow( ndcZ, depthPackExponent ) * ( farPlaneDist - nearPlaneDist ) + nearPlaneDist;
}
pow襯狩牛ndcZ襯殊覿襦覲. 讌ろ襴渚碁ゼ牛伎^讌襷蠍磯蓋朱2襯殊螻給. 願屋螻
ndcZ覿れ螻手企蟆.
螳襦豢ndcZ手螳碁豢豺覲螳襷螻螳蠍蟆伎蟆覲殊給. 企ゼ牛伎拘
覃殊螳蟾伎豺譬伎襯殊螻牛蟆.
伎詞NDC 螻糾譬豺企手概螳蟾願牛伎豺襯手壱給.
/*
- input
ndc : NDC 螻糾 譬
depth : 豺企 螻糾 蟾 螳
Volumetric Fog 4
- global parameter
InvProjectionMatrix : 覲 
InvViewMatrix : 豺企 覲 
- output
 螻糾 譬
*/
float3 ConvertToWorldPosition( float3 ndc, float depth )
{
// view ray
// ndc譬  豺企 螻糾 蟯 螻
float4 viewRay = mul( float4( ndc, 1.f ), InvProjectionMatrix );
viewRay /= viewRay.w;
viewRay /= viewRay.z; // z螳 1 襦
// ndc -> world position
float4 worldPosition = mul( float4( viewRay.xyz * depth, 1.f ), InvViewMatrix );
return worldPosition.xyz;
}
磯覦鰢螻
磯螻
磯伎豢譯朱朱伎. 觜伎螻旧伎企るГ讌糾骸覃企Г讌豢
覦レ朱覿磯蟇磯′. 企螻覲朱エれ螳豺豺企手讌朱襷觜伎磯讌襯手壱螻
磯螻襷れ覦襯手鍵襦.
Phase function
襾殊觜伎朱磯讌螻壱蠍一伎phase function.
phase function觜企覦レ朱朱磯讌襯朱企. 危譟磯覯″一螳覦ル押一伎螳
碁一讌覲伎ヾ覯豺磯ゴ蠍磯覓語覈覦レ伎覿覃1企. (phase function′螳螻るる1
覲企れ給.)
phase function磯譬襯磯朱螳讌螳Volumetric Fog 蟲Henyey-Greenstein phase function 襯殊
.
Henyey-Greenstein phase function
企逢炎g螳磯ジ蠏碁
Henyey-Greenstein phase function覩(Mie) 磯螻手企逢煙磯覡伎螳レ朱phase function.
覩語磯觜リ骸蠍郁觜訣豢覦磯朱蟲襴企觜螳り鍵企蟆覲伎企蟆覩語磯
.
/*
- input
wi : 觜 れ伎る 覦
wo : 觜 螳 覦
p(慮) =
4
1
(1 + g  2gcos慮)
2 2
3
1  g2
Volumetric Fog 5
g : 企逢 螻
- output
wi れ伎 wo襦 螳 觜 
*/
float HenyeyGreensteinPhaseFunction( float3 wi, float3 wo, float g )
{
float cosTheta = dot( wi, wo );
float g2 = g * g;
float denom = pow( 1.f + g2 - 2.f * g * cosTheta, 3.f / 2.f );
return ( 1.f / ( 4.f * PI ) ) * ( ( 1.f - g2 ) / max( denom, EPSILON ) );
}
HenyeyGreensteinPhaseFunction伎企骸襯れ螳豺企朱逢レ朱磯觜螻壱給.
覦螻
襴磯語伎れ襯殊伎蟇磯伎磯殊朱覿襯殊襷れ覿蠏燕覦襯狩讌襷蟆郁骸
覓殊襷れ覦螳蠏燕蟆曙磯蟲給. 磯殊覲朱エれ蠍磯覦れ螻手給.
/*
UniformDensity : 蠏燕 覦
*/
float density = UniformDensity;
磯螻郁骸覦螻一豺貉危語一企貊れ螻手給.
磯觜覲朱エれrgb豈覦a豈ロ.
/*
- global parameter
FrustumVolume : 覲朱エ れ
CameraPos : 豺企 豺
UniformDensity : 蠏燕 覦
HemisphereUpperColor : Ambient襦  覦蟲 譟磯 
Intensity : 觜 螳 譟一  覲
*/
[numthreads( 8, 8, 8 )]
void main( uint3 DTid : SV_DispatchThreadId )
{
uint3 dims;
FrustumVolume.GetDimensions( dims.x, dims.y, dims.z );
if ( all( DTid < dims ) )
{
float3 worldPosition = ConvertThreadIdToWorldPosition( DTid, dims );
float3 toCamera = normalize( CameraPos - worldPosition );
float density = UniformDensity;
float3 lighting = HemisphereUpperColor.rgb * HemisphereUpperColor.a;
[loop]
for ( uint i = 0; i < NumLights; ++i )
{
ForwardLightData light = GetLight( i );
float3 lightDirection = { 0.f, 0.f, 0.f };
if ( length( light.m_direction ) > 0.f ) // Directional Light 蟆曙
{
lightDirection = normalize( light.m_direction );
}
else // 蠏 語 蟆曙 (Point, Spot)
{
lightDirection = normalize( worldPosition - light.m_position );
}
float3 toLight = -lightDirection;
float visibility = Visibility( worldPosition, toLight ); //  襷旧朱 螳 蟆
float phaseFunction = HenyeyGreensteinPhaseFunction( lightDirection, toCamera, AsymmetryParameterG );
lighting += visibility * light.m_diffuse.rgb * light.m_diffuse.a * phaseFunction;
}
FrustumVolume[DTid] = float4( lighting * Intensity * density, density )
Volumetric Fog 6
}
}
磯
螻覲朱エれ螳豺豺企朱逢レ朱磯觜螻朱襯手壱給. 讌蠍蟾讌覲朱エれ
ル覲企讌3谿螻糾磯讌讌給.
磯螻豺豺企手讌觜伎企蟆暑磯螻觜企Г讌糾骸覃伎覦觜螳
覡伎.
Beer-Lambert 覯豺
Beer-Lambert 覯豺襷れ煙螻朱螳覯豺. 企豺螻殊壱螻殊譯殊伎覦レ
伎る觜企Г讌牛伎觜襦A豺B蟾讌螻殊朱朱れ螻手伎.
蠍一 磯螻狩′朱覃瑚. 願規覦螳 螳.
螻殊蠏碁襦蠏碁る慨覃伎螳願碓襴磯殊朱螳蟆誤給.
Beer-Lambert 覯豺Ubisoft覦襭れ螻手貊襯殊螻給.
T(A  B) = e 硫 (x)dx
B
A
e
硫e 硫e
Volumetric Fog 7
蠏碁SIGGRAPH 2015Frostbite螳覦Physically Based and Unified Volumetric Rendering in Frostbite磯ゴ覃伎
覦讌覲伎ヾ覯豺譴讌螻伎襦企覦螻給.
磯螻 螳貉れ磯殊覦讌蟆誤給. Frostbite螳蠍壱碁れ覩誤谿瑚蠍磯
.
: 覲朱エれ蟾讌蟾(= 襷れ觜企蟇磯Μ)
: 磯螻狩′襯狩豺覃瑚(= 蟲貊覦)
: 磯譟磯
朱覲手規貊Frostbite覦給.
覦レ豺企殊豺螳蟾願崖襾手崖朱企覃磯. 讀覲朱エれ蟾0覿一蟆.
s
D
t
S
Volumetric Fog 8
伎磯ジ貉危語一企貊れ螻手給.
RWTexture3D<float4> FrustumVolume : register( t0 );
[numthreads( 8, 8, 1 )]
void main( uint3 DTid : SV_DispatchThreadID )
{
uint3 dims;
FrustumVolume .GetDimensions( dims.x, dims.y, dims.z );
if ( all( DTid < dims ) )
{
float4 accum = float4( 0.f, 0.f, 0.f, 1.f );
uint3 pos = uint3( DTid.xy, 0 );
[loop]
for ( uint z = 0; z < dims.z; ++z )
{
pos.z = z;
float4 slice = FrustumVolume[pos];
float tickness = SliceTickness( (float)z / dims.z, dims.z );
accum = ScatterStep( accum.rgb, accum.a, slice.rgb, slice.a, tickness );
FrustumVolume [pos] = accum;
}
}
}
SliceTickness襯狩牛伎覲朱エれ豺豺語谿企ゼ牛伎覿螳蟾企蟷襯手壱. 企蟷螳
.
/*
- input
ndc : NDC 螻糾 譬
dimZ : 覲朱エ れ 蟾
- output
蟾 蟷
*/
float SliceTickness( float ndcZ, uint dimZ )
{
return ConvertNdcZToDepth( ndcZ + 1.f / float( dimZ ) ) - ConvertNdcZToDepth( ndcZ );
}
れ伎企讌ScatterStep れ螻手給.
/*
- input
accumulatedLight :  譟磯
accumulatedTransmittance :  螻殊
sliceLight :  豺 譟磯
sliceDensity :  豺 覦
tickness : 蟾 蟷
- global constant
DensityScale : 覦  れ(蠏狩 覦 朱誤磯ゼ   譬   螳朱 蠍   譟一 豺)
- output
 觜(rgb)螻 螻殊(a)
*/
D
Volumetric Fog 9
static const float DensityScale = 0.01f;
float4 ScatterStep( float3 accumulatedLight, float accumulatedTransmittance, float3 sliceLight, float sliceDensity, float tickness )
{
sliceDensity = max( sliceDensity, 0.000001f );
sliceDensity *= DensityScale;
float sliceTransmittance = exp( -sliceDensity * tickness );
// Frostbite  覦
float3 sliceLightIntegral = sliceLight * ( 1.f - sliceTransmittance ) / sliceDensity;
accumulatedLight += sliceLightIntegral * accumulatedTransmittance;
accumulatedTransmittance *= sliceTransmittance;
return float4( accumulatedLight, accumulatedTransmittance );
}
Fog 
伎譴觜螻殊覈給. 螻覃危伎襷殊螳蠏碁れル伎Fog襯殊. 願骸
譯殊ろ危碁れ螻手給.
// SrcAlpha襦 觚
BlendOption volumetricFogDrawPassBlendOption;
RenderTargetBlendOption& rt0BlendOption = volumetricFogDrawPassBlendOption.m_renderTarget[0];
rt0BlendOption.m_blendEnable = true;
rt0BlendOption.m_srcBlend = agl::Blend::One;
rt0BlendOption.m_destBlend = agl::Blend::SrcAlpha;
rt0BlendOption.m_srcBlendAlpha = agl::Blend::Zero;
rt0BlendOption.m_destBlendAlpha = agl::Blend::One;
// 蟾 ろ 覦 郁鍵 OFF
DepthStencilOption depthStencilOption;
depthStencilOption.m_depth.m_enable = false;
depthStencilOption.m_depth.m_writeDepth = false;
曙一企螳曙豺企手概螳譬襯手壱伎企轟襯朱骸襯れUV襦覲蟆渚れ襷. 觚ろ危
SrcAlpha襦觚襦れ蠍磯覓語螻殊企願鹸覲朱エれ豈蠏碁襦覃危螻殊1螳蟾語襦
危螻殊0螳蟾語襦磯觜企.
float4 main( PS_INPUT input ) : SV_Target0
{
float viewSpaceDistance = ViewSpaceDistance.Sample( ViewSpaceDistanceSampler, input.uv ).x;
if ( viewSpaceDistance <= 0.f )
{
viewSpaceDistance = FarPlaneDist;
}
float3 viewPosition = normalize( input.viewRay ) * viewSpaceDistance;
float3 uv = float3( input.uv, ConvertDepthToNdcZ( viewPosition.z ) );
float4 scatteringColorAndTransmittance = AccumulatedVolume.Sample( AccumulatedVolumeSampler, uv );
float3 scatteringColor = HDR( scatteringColorAndTransmittance.rgb );
return float4( scatteringColor, scatteringColorAndTransmittance.a );
}
讌レ螳
蠍郁讌蠍磯蓋Volumetric Fog蟲覦覯危エ覲伎給. 讌蠍覿磯讌レ螳2螳讌襯殊螳螻螻
襯朱蟲企慨蟆給.
1) Temporal reprojection
Ubisoft覦襭覲朱エれ蠍磯720p 蠍一160x90x128. 覲朱エれ伎螳覃伎伎覲企れ
蠍磯覓語一朱覲朱エれ螳曙貉る蟆.
720p螳襦碁(1280 x 720)襯朱骸襯れ襦覲企願襦碁8曙豐64曙貉る螻給. 64曙企
狩磯螳伎狩覩襦Volumetric Fog碁襷朱誤壱瑚覦.
Volumetric Fog 10
Temporal reprojection企一壱碁ゼ蟇壱蠍一伎. Temporal 企朱伎Temporal Anti-
Aliasing螻朱谿螳讌襦伎螻壱蟆郁骸襯朱碁襷願屋る覦. 磯殊伎覲企ゼ
讌蠍一企れれ螳.
// 伎 ,   れ 2螳, れ覃伎 
for ( agl::RefHandle<agl::Texture>& frustumVolume : m_frustumVolume )
{
frustumVolume = agl::Texture::Create( frustumVolumeTrait );
EnqueueRenderTask(
[texture = frustumVolume]()
{
texture->Init();
} );
}
// 磯  螻  蟆郁骸 れ 1螳
m_accumulatedVolume = agl::Texture::Create( frustumVolumeTrait );
EnqueueRenderTask(
[texture = m_accumulatedVolume]()
{
texture->Init();
} );
Temporal Anti-Aliasing企Гjitter襯狩牛企襷覓殊牡豺襯殊^蠍願蟆蟆豌Temporal reprojection
jitter襯狩牛企骸襯れ豺襯殊^蠍願蟆.
蠍一Halton Sequence襯殊給. (Halton Sequenceる伎Temporal Anti-Aliasing 伎襯殊宛螻覿襴暑
.) 3谿螻糾jitter襯殊Halton Sequence3谿朱ロ給.
// 2, 3, 5()襦 觸 
static const float3 HALTON_SEQUENCE[MAX_HALTON_SEQUENCE] = {
float3( 0.5, 0.333333, 0.2 ),
float3( 0.25, 0.666667, 0.4 ),
float3( 0.75, 0.111111, 0.6 ),
float3( 0.125, 0.444444, 0.8 ),
float3( 0.625, 0.777778, 0.04 ),
float3( 0.375, 0.222222, 0.24 ),
float3( 0.875, 0.555556, 0.44 ) ,
float3( 0.0625, 0.888889, 0.64 ),
float3( 0.5625, 0.037037, 0.84 ),
float3( 0.3125, 0.37037, 0.08 ),
float3( 0.8125, 0.703704, 0.28 ),
float3( 0.1875, 0.148148, 0.48 ),
float3( 0.6875, 0.481482, 0.68 ),
float3( 0.4375, 0.814815, 0.88 ),
float3( 0.9375, 0.259259, 0.12 ),
float3( 0.03125, 0.592593, 0.32 )
};
磯覦鰢螻磯螻れ螻手jitter襯殊螳.
float3 jitter = HALTON_SEQUENCE[( FrameCount + DTid.x + DTid.y * 2 ) % MAX_HALTON_SEQUENCE];
jitter.xyz -= 0.5f; // -0.5 ~ 0.5 覯襦 譟一
// jitter螳   豺
float3 worldPosition = ConvertThreadIdToWorldPosition( DTid, dims, jitter );
Volumetric Fog 11
蠏碁Μ螻伎覲願る(=豺企朱朱螳讌る) 螻殊給.
/*
- Global Parameter
TemporalAccum : Temporal reprojection  覿, 豌  蟶殊狩   ( 伎  覲願 蠍 覓 )
PrevViewProjectionMatrix : 伎  豺企  
*/
Texture3D HistoryVolume : register( t0 );
SamplerState HistorySampler : register( s0 );
// ...
// Main  企   磯 螻 
curScattering = float4( lighting * Intensity * density, density );
if ( TemporalAccum > 0.f )
{
float3 worldPosWithoutJitter = ConvertThreadIdToWorldPosition( DTid, dims );
// 伎  UV 螻
float3 prevFrameUV = ConvertWorldPositionToUV( worldPosWithoutJitter, PrevViewProjectionMatrix );
// 0 ~ 1 覯覃 
if ( all( prevFrameUV <= ( float3 )1.f ) && all( prevFrameUV >= ( float3 )0.f ) )
{
float4 prevScattering = HistoryVolume.SampleLevel( HistorySampler, prevFrameUV, 0 );
curScattering = lerp( prevScattering, curScattering, 0.05f );
}
}
FrustumVolume[DTid] = curScattering;
磯螻磯螻覲覲朱エれ豢ロ襦給.
AccumulatedVolume[pos] = accum;
襯朱蟲企慨覃企れ螻手給.
2) Tricubic texture sampling
覲旧一危一襷覦覲蟆渚蟆朱豢螳誤讌レ詞給. Tricubic texture samplingCUDA
Cubic B-Spline Interpolation磯ジ覦朱覲朱エれ襯B-Spline牛企慨螳. 襷覲企る蟆郁骸襯手谿壱
給.
Volumetric Fog 12
豢豌: https://twitter.com/FewesW/status/1300045087938879489
蟲一Tricubic sampling 貊襯手誤襦語襷蟆所Fog 螻給.
#if TricubicTextureSampling == 1
float4 scatteringColorAndTransmittance = Tex3DTricubic( AccumulatedVolume, AccumulatedVolumeSampler, uv);
#else
float4 scatteringColorAndTransmittance = AccumulatedVolume.Sample( AccumulatedVolumeSampler, uv );
#endif
襯朱蟲企慨覃企れ螻手給.
襷豺覃
碁Μ殊讌Volumetric Fog蟲蠍磯る伎螻狩蟆るゴ讌給. 覈螳讌螳(Temporal reprojection ろ襭襯
觜襯願危襦)伎讌襷螳企襴磯伎覦朱豢覿危危手螳
. 碁Μ殊蟲豢螳襦危エ覲願苦殊覿企企讌覈螻褐蠍一蠍磯襦蟆給.
VolumetricFog.cpp : 貉危語一企襯殊Volumetric Fog 磯螻一れ企.
ComputeVolumetricFog() : 螳レ讌.
GetVolumetricFogGridSize() : 覲朱エれ蠍郁壱.
GetVolumetricFogGridZParams() : Z豢覿朱誤郁壱, 碁Μ殊れ螻手覿襯朱磯ゴ襦Z
豢覿郁啓覃伎覓企伎螳豪蟆覦讌蠍一朱螳.
Volumetric Fog 13
VoxelizeFogVolumePrimitives() : Volume 襾誤磯Μ殊牛企襷襴覩誤磯襯朱概伎Volumetric Fog 覲朱エ
れ襷. 企ゼ牛企れ覦襯狩給. 蟲螳讌Voxelize 覈螳給.
FVolumetricFogLightScatteringCS : 磯螻一惨語一企企れ.
FVolumetricFogFinalIntegrationCS : 磯貉危語一企企れ.
RenderViewFog() : Fog襯朱襷.
FExponentialHeightFogPS : Fog襯朱襷曙一企企れ.
譴觜伎蠍郁讌. 螳誤襦瑚規豌伎github襯殊宛螻覿襴暑.
GitHub - xtozero/SSR at volumetric_fog
Screen Space Reflection. Contribute to xtozero/SSR development by creating an account on GitHub.
https://github.com/xtozero/SSR/tree/volumetric_fog
螳.
Reference
https://github.com/diharaw/volumetric-fog : opengl 蟲
https://github.com/bartwronski/CSharpRenderer : 蟲
https://github.com/Unity-Technologies/VolumetricLighting/tree/master/Assets/VolumetricFog : Unity蟲

More Related Content

Volumetric Fog

  • 1. Volumetric Fog 1 Volumetric Fog 覈谿 1. Volumetric Fog 2. 蟲覦覯 3. 覲朱エれ 4. 磯覦鰢螻 a. 磯螻 i. Phase function b. 覦螻 5. 磯 a. Beer-Lambert 覯豺 6. Fog 7. 讌レ螳 a. Temporal reprojection b. Tricubic texture sampling 8. 襷豺覃 9. Reference Volumetric Fog Volumetric Fog覓朱Μ蠍磯譟磯磯螻壱豌伎語螳襯狩蠍磯. 螳語觜覲企ろ誤襦語るゼ 豌危螳企ゼ磯給. Volumetric FogSIGGRAPH 2014Ubisoft螳覦Volumetric fog: Unified, compute shader based solution to atmospheric scattering 牛伎螳給. 願企轟襭襯手鍵覦朱Direct3D 11/12襦蟲蟆郁骸覓殊牛 Volumetric Fog蠍磯蓋瑚規覦覯螳螻碁Μ殊讌Volumetric Fog螳企至蟲伎讌危エ覲企襦蟆給 . 蟲覦覯 Volumetric Fogれ螻手襦蟲. 1. 豌伎覲朱エれ襯殊 2. 貉危語一企襯狩牛企骸襯れ螳磯覦鰢螻
  • 2. Volumetric Fog 2 3. 豺企朱一蟇磯Μ磯ジ磯 4. SceneFog 危襦螳螻襯殊誤覲企襦蟆給. 覲朱エれ 螳ル┝覲朱エれ襯殊燕螳給. 覲朱エれ3D螻糾磯覦鰢覲企ゼロ一. 覦襭磯ゴ覃企骸襯れ蠍磯720p蠍一朱弰磯160x90x64(螳襦x碁x蟾) 轟160x90x128企壱襷血朱 16bit RGBA Float襯殊り. 160x90x128 蠍一覲朱エれ襯UAVSRV襦襦燕給. 覲朱エれ煙れれ 螻手給. const std::array<uint32, 3>& frustumGridSize = Proxy()->FrustumGridSize(); agl::TextureTrait frustumVolumeTrait = { .m_width = frustumGridSize[0], // 160 .m_height = frustumGridSize[1], // 90 .m_depth = frustumGridSize[2], // 128 .m_sampleCount = 1, .m_sampleQuality = 0, .m_mipLevels = 1, .m_format = agl::ResourceFormat::R16G16B16A16_FLOAT, .m_access = agl::ResourceAccessFlag::GpuRead | agl::ResourceAccessFlag::GpuWrite, .m_bindType = agl::ResourceBindType::RandomAccess | agl::ResourceBindType::ShaderResource, .m_miscFlag = agl::ResourceMisc::Texture3D }; 企蟆燕覲朱エれ螳豺企手概螳殊覲旧磯覦鰢覲企ゼロ壱れ蠍一曙 蠍磯覓語豺企手概螳蠏燕蟆覿蟆伎手蟾願崖伎襯殊螻牛蠍一z豢(豺企手覲企覦) 讌 覿襯朱磯ゴ襦覿. 覲朱エれid襯朱螻糾譬襦覲襯狩牛伎誤螻糾覿螻殊覲 蟆給. /* - input id : 覲朱エ れ id (x,y,z) dims : 覲朱エ れ 蠍 (width, height, depth) - output 螻糾 譬 */ float3 ConvertThreadIdToWorldPosition( uint3 id, uint3 dims ) { // id -> ndc float3 ndc = ConvertThreadIdToNdc( id, dims ); float depth = ConvertNdcZToDepth( ndc.z ); return ConvertToWorldPosition( ndc, depth ); } 襾殊覲朱エれidれ蠍磯ゼ語襦覦NDC(Normalized Device Coordinate) 螻糾朱覲蟆渚. 願骸企 覲ConvertThreadIdToNdcれ螻手給. /* - input
  • 3. Volumetric Fog 3 id : 覲朱エ れ id (x,y,z) dims : 覲朱エ れ 蠍 (width, height, depth) - output Direct3D 殊 譬螻襯 磯ゴ覩襦 X,Y 螳 -1 ~ 1 Z螳 0 ~ 1 覯 NDC 螻糾 譬 */ float3 ConvertThreadIdToNdc( uint3 id, uint3 dims ) { float3 ndc = id; ndc += 0.5f; ndc *= float3( 2.f / dims.x, -2.f / dims.y, 1.f / dims.z ); ndc += float3( -1.f, 1.f, 0.f ); return ndc; } NDC 螻糾譬襯殊至覃Z譬螳牛伎覿襯朱磯朱豺企手概螳蟾願詞給. 願骸 ConvertNdcZToDepth企讌. /* - input ndcZ : NDC 螻糾 Z譬 - global parameter VolumetricFogParam.DepthPackExponent : 讌 覿 覲 讌 VolumetricFogParam.NearPlaneDist : Fog 蠏狩覃願讌 蟇磯Μ VolumetricFogParam.FarPlaneDist : Fog 覃願讌 蟇磯Μ - ouput 讌 覿襯 磯朱 豺企 螻糾 蟾 */ float ConvertNdcZToDepth( float ndcZ ) { float depthPackExponent = VolumetricFogParam.DepthPackExponent; float nearPlaneDist = VolumetricFogParam.NearPlaneDist; float farPlaneDist = VolumetricFogParam.FarPlaneDist; return pow( ndcZ, depthPackExponent ) * ( farPlaneDist - nearPlaneDist ) + nearPlaneDist; } pow襯狩牛ndcZ襯殊覿襦覲. 讌ろ襴渚碁ゼ牛伎^讌襷蠍磯蓋朱2襯殊螻給. 願屋螻 ndcZ覿れ螻手企蟆. 螳襦豢ndcZ手螳碁豢豺覲螳襷螻螳蠍蟆伎蟆覲殊給. 企ゼ牛伎拘 覃殊螳蟾伎豺譬伎襯殊螻牛蟆. 伎詞NDC 螻糾譬豺企手概螳蟾願牛伎豺襯手壱給. /* - input ndc : NDC 螻糾 譬 depth : 豺企 螻糾 蟾 螳
  • 4. Volumetric Fog 4 - global parameter InvProjectionMatrix : 覲 InvViewMatrix : 豺企 覲 - output 螻糾 譬 */ float3 ConvertToWorldPosition( float3 ndc, float depth ) { // view ray // ndc譬 豺企 螻糾 蟯 螻 float4 viewRay = mul( float4( ndc, 1.f ), InvProjectionMatrix ); viewRay /= viewRay.w; viewRay /= viewRay.z; // z螳 1 襦 // ndc -> world position float4 worldPosition = mul( float4( viewRay.xyz * depth, 1.f ), InvViewMatrix ); return worldPosition.xyz; } 磯覦鰢螻 磯螻 磯伎豢譯朱朱伎. 觜伎螻旧伎企るГ讌糾骸覃企Г讌豢 覦レ朱覿磯蟇磯′. 企螻覲朱エれ螳豺豺企手讌朱襷觜伎磯讌襯手壱螻 磯螻襷れ覦襯手鍵襦. Phase function 襾殊觜伎朱磯讌螻壱蠍一伎phase function. phase function觜企覦レ朱朱磯讌襯朱企. 危譟磯覯″一螳覦ル押一伎螳 碁一讌覲伎ヾ覯豺磯ゴ蠍磯覓語覈覦レ伎覿覃1企. (phase function′螳螻るる1 覲企れ給.) phase function磯譬襯磯朱螳讌螳Volumetric Fog 蟲Henyey-Greenstein phase function 襯殊 . Henyey-Greenstein phase function 企逢炎g螳磯ジ蠏碁 Henyey-Greenstein phase function覩(Mie) 磯螻手企逢煙磯覡伎螳レ朱phase function. 覩語磯觜リ骸蠍郁觜訣豢覦磯朱蟲襴企觜螳り鍵企蟆覲伎企蟆覩語磯 . /* - input wi : 觜 れ伎る 覦 wo : 觜 螳 覦 p(慮) = 4 1 (1 + g 2gcos慮) 2 2 3 1 g2
  • 5. Volumetric Fog 5 g : 企逢 螻 - output wi れ伎 wo襦 螳 觜 */ float HenyeyGreensteinPhaseFunction( float3 wi, float3 wo, float g ) { float cosTheta = dot( wi, wo ); float g2 = g * g; float denom = pow( 1.f + g2 - 2.f * g * cosTheta, 3.f / 2.f ); return ( 1.f / ( 4.f * PI ) ) * ( ( 1.f - g2 ) / max( denom, EPSILON ) ); } HenyeyGreensteinPhaseFunction伎企骸襯れ螳豺企朱逢レ朱磯觜螻壱給. 覦螻 襴磯語伎れ襯殊伎蟇磯伎磯殊朱覿襯殊襷れ覿蠏燕覦襯狩讌襷蟆郁骸 覓殊襷れ覦螳蠏燕蟆曙磯蟲給. 磯殊覲朱エれ蠍磯覦れ螻手給. /* UniformDensity : 蠏燕 覦 */ float density = UniformDensity; 磯螻郁骸覦螻一豺貉危語一企貊れ螻手給. 磯觜覲朱エれrgb豈覦a豈ロ. /* - global parameter FrustumVolume : 覲朱エ れ CameraPos : 豺企 豺 UniformDensity : 蠏燕 覦 HemisphereUpperColor : Ambient襦 覦蟲 譟磯 Intensity : 觜 螳 譟一 覲 */ [numthreads( 8, 8, 8 )] void main( uint3 DTid : SV_DispatchThreadId ) { uint3 dims; FrustumVolume.GetDimensions( dims.x, dims.y, dims.z ); if ( all( DTid < dims ) ) { float3 worldPosition = ConvertThreadIdToWorldPosition( DTid, dims ); float3 toCamera = normalize( CameraPos - worldPosition ); float density = UniformDensity; float3 lighting = HemisphereUpperColor.rgb * HemisphereUpperColor.a; [loop] for ( uint i = 0; i < NumLights; ++i ) { ForwardLightData light = GetLight( i ); float3 lightDirection = { 0.f, 0.f, 0.f }; if ( length( light.m_direction ) > 0.f ) // Directional Light 蟆曙 { lightDirection = normalize( light.m_direction ); } else // 蠏 語 蟆曙 (Point, Spot) { lightDirection = normalize( worldPosition - light.m_position ); } float3 toLight = -lightDirection; float visibility = Visibility( worldPosition, toLight ); // 襷旧朱 螳 蟆 float phaseFunction = HenyeyGreensteinPhaseFunction( lightDirection, toCamera, AsymmetryParameterG ); lighting += visibility * light.m_diffuse.rgb * light.m_diffuse.a * phaseFunction; } FrustumVolume[DTid] = float4( lighting * Intensity * density, density )
  • 6. Volumetric Fog 6 } } 磯 螻覲朱エれ螳豺豺企朱逢レ朱磯觜螻朱襯手壱給. 讌蠍蟾讌覲朱エれ ル覲企讌3谿螻糾磯讌讌給. 磯螻豺豺企手讌觜伎企蟆暑磯螻觜企Г讌糾骸覃伎覦觜螳 覡伎. Beer-Lambert 覯豺 Beer-Lambert 覯豺襷れ煙螻朱螳覯豺. 企豺螻殊壱螻殊譯殊伎覦レ 伎る觜企Г讌牛伎觜襦A豺B蟾讌螻殊朱朱れ螻手伎. 蠍一 磯螻狩′朱覃瑚. 願規覦螳 螳. 螻殊蠏碁襦蠏碁る慨覃伎螳願碓襴磯殊朱螳蟆誤給. Beer-Lambert 覯豺Ubisoft覦襭れ螻手貊襯殊螻給. T(A B) = e 硫 (x)dx B A e 硫e 硫e
  • 7. Volumetric Fog 7 蠏碁SIGGRAPH 2015Frostbite螳覦Physically Based and Unified Volumetric Rendering in Frostbite磯ゴ覃伎 覦讌覲伎ヾ覯豺譴讌螻伎襦企覦螻給. 磯螻 螳貉れ磯殊覦讌蟆誤給. Frostbite螳蠍壱碁れ覩誤谿瑚蠍磯 . : 覲朱エれ蟾讌蟾(= 襷れ觜企蟇磯Μ) : 磯螻狩′襯狩豺覃瑚(= 蟲貊覦) : 磯譟磯 朱覲手規貊Frostbite覦給. 覦レ豺企殊豺螳蟾願崖襾手崖朱企覃磯. 讀覲朱エれ蟾0覿一蟆. s D t S
  • 8. Volumetric Fog 8 伎磯ジ貉危語一企貊れ螻手給. RWTexture3D<float4> FrustumVolume : register( t0 ); [numthreads( 8, 8, 1 )] void main( uint3 DTid : SV_DispatchThreadID ) { uint3 dims; FrustumVolume .GetDimensions( dims.x, dims.y, dims.z ); if ( all( DTid < dims ) ) { float4 accum = float4( 0.f, 0.f, 0.f, 1.f ); uint3 pos = uint3( DTid.xy, 0 ); [loop] for ( uint z = 0; z < dims.z; ++z ) { pos.z = z; float4 slice = FrustumVolume[pos]; float tickness = SliceTickness( (float)z / dims.z, dims.z ); accum = ScatterStep( accum.rgb, accum.a, slice.rgb, slice.a, tickness ); FrustumVolume [pos] = accum; } } } SliceTickness襯狩牛伎覲朱エれ豺豺語谿企ゼ牛伎覿螳蟾企蟷襯手壱. 企蟷螳 . /* - input ndc : NDC 螻糾 譬 dimZ : 覲朱エ れ 蟾 - output 蟾 蟷 */ float SliceTickness( float ndcZ, uint dimZ ) { return ConvertNdcZToDepth( ndcZ + 1.f / float( dimZ ) ) - ConvertNdcZToDepth( ndcZ ); } れ伎企讌ScatterStep れ螻手給. /* - input accumulatedLight : 譟磯 accumulatedTransmittance : 螻殊 sliceLight : 豺 譟磯 sliceDensity : 豺 覦 tickness : 蟾 蟷 - global constant DensityScale : 覦 れ(蠏狩 覦 朱誤磯ゼ 譬 螳朱 蠍 譟一 豺) - output 觜(rgb)螻 螻殊(a) */ D
  • 9. Volumetric Fog 9 static const float DensityScale = 0.01f; float4 ScatterStep( float3 accumulatedLight, float accumulatedTransmittance, float3 sliceLight, float sliceDensity, float tickness ) { sliceDensity = max( sliceDensity, 0.000001f ); sliceDensity *= DensityScale; float sliceTransmittance = exp( -sliceDensity * tickness ); // Frostbite 覦 float3 sliceLightIntegral = sliceLight * ( 1.f - sliceTransmittance ) / sliceDensity; accumulatedLight += sliceLightIntegral * accumulatedTransmittance; accumulatedTransmittance *= sliceTransmittance; return float4( accumulatedLight, accumulatedTransmittance ); } Fog 伎譴觜螻殊覈給. 螻覃危伎襷殊螳蠏碁れル伎Fog襯殊. 願骸 譯殊ろ危碁れ螻手給. // SrcAlpha襦 觚 BlendOption volumetricFogDrawPassBlendOption; RenderTargetBlendOption& rt0BlendOption = volumetricFogDrawPassBlendOption.m_renderTarget[0]; rt0BlendOption.m_blendEnable = true; rt0BlendOption.m_srcBlend = agl::Blend::One; rt0BlendOption.m_destBlend = agl::Blend::SrcAlpha; rt0BlendOption.m_srcBlendAlpha = agl::Blend::Zero; rt0BlendOption.m_destBlendAlpha = agl::Blend::One; // 蟾 ろ 覦 郁鍵 OFF DepthStencilOption depthStencilOption; depthStencilOption.m_depth.m_enable = false; depthStencilOption.m_depth.m_writeDepth = false; 曙一企螳曙豺企手概螳譬襯手壱伎企轟襯朱骸襯れUV襦覲蟆渚れ襷. 觚ろ危 SrcAlpha襦觚襦れ蠍磯覓語螻殊企願鹸覲朱エれ豈蠏碁襦覃危螻殊1螳蟾語襦 危螻殊0螳蟾語襦磯觜企. float4 main( PS_INPUT input ) : SV_Target0 { float viewSpaceDistance = ViewSpaceDistance.Sample( ViewSpaceDistanceSampler, input.uv ).x; if ( viewSpaceDistance <= 0.f ) { viewSpaceDistance = FarPlaneDist; } float3 viewPosition = normalize( input.viewRay ) * viewSpaceDistance; float3 uv = float3( input.uv, ConvertDepthToNdcZ( viewPosition.z ) ); float4 scatteringColorAndTransmittance = AccumulatedVolume.Sample( AccumulatedVolumeSampler, uv ); float3 scatteringColor = HDR( scatteringColorAndTransmittance.rgb ); return float4( scatteringColor, scatteringColorAndTransmittance.a ); } 讌レ螳 蠍郁讌蠍磯蓋Volumetric Fog蟲覦覯危エ覲伎給. 讌蠍覿磯讌レ螳2螳讌襯殊螳螻螻 襯朱蟲企慨蟆給. 1) Temporal reprojection Ubisoft覦襭覲朱エれ蠍磯720p 蠍一160x90x128. 覲朱エれ伎螳覃伎伎覲企れ 蠍磯覓語一朱覲朱エれ螳曙貉る蟆. 720p螳襦碁(1280 x 720)襯朱骸襯れ襦覲企願襦碁8曙豐64曙貉る螻給. 64曙企 狩磯螳伎狩覩襦Volumetric Fog碁襷朱誤壱瑚覦.
  • 10. Volumetric Fog 10 Temporal reprojection企一壱碁ゼ蟇壱蠍一伎. Temporal 企朱伎Temporal Anti- Aliasing螻朱谿螳讌襦伎螻壱蟆郁骸襯朱碁襷願屋る覦. 磯殊伎覲企ゼ 讌蠍一企れれ螳. // 伎 , れ 2螳, れ覃伎 for ( agl::RefHandle<agl::Texture>& frustumVolume : m_frustumVolume ) { frustumVolume = agl::Texture::Create( frustumVolumeTrait ); EnqueueRenderTask( [texture = frustumVolume]() { texture->Init(); } ); } // 磯 螻 蟆郁骸 れ 1螳 m_accumulatedVolume = agl::Texture::Create( frustumVolumeTrait ); EnqueueRenderTask( [texture = m_accumulatedVolume]() { texture->Init(); } ); Temporal Anti-Aliasing企Гjitter襯狩牛企襷覓殊牡豺襯殊^蠍願蟆蟆豌Temporal reprojection jitter襯狩牛企骸襯れ豺襯殊^蠍願蟆. 蠍一Halton Sequence襯殊給. (Halton Sequenceる伎Temporal Anti-Aliasing 伎襯殊宛螻覿襴暑 .) 3谿螻糾jitter襯殊Halton Sequence3谿朱ロ給. // 2, 3, 5()襦 觸 static const float3 HALTON_SEQUENCE[MAX_HALTON_SEQUENCE] = { float3( 0.5, 0.333333, 0.2 ), float3( 0.25, 0.666667, 0.4 ), float3( 0.75, 0.111111, 0.6 ), float3( 0.125, 0.444444, 0.8 ), float3( 0.625, 0.777778, 0.04 ), float3( 0.375, 0.222222, 0.24 ), float3( 0.875, 0.555556, 0.44 ) , float3( 0.0625, 0.888889, 0.64 ), float3( 0.5625, 0.037037, 0.84 ), float3( 0.3125, 0.37037, 0.08 ), float3( 0.8125, 0.703704, 0.28 ), float3( 0.1875, 0.148148, 0.48 ), float3( 0.6875, 0.481482, 0.68 ), float3( 0.4375, 0.814815, 0.88 ), float3( 0.9375, 0.259259, 0.12 ), float3( 0.03125, 0.592593, 0.32 ) }; 磯覦鰢螻磯螻れ螻手jitter襯殊螳. float3 jitter = HALTON_SEQUENCE[( FrameCount + DTid.x + DTid.y * 2 ) % MAX_HALTON_SEQUENCE]; jitter.xyz -= 0.5f; // -0.5 ~ 0.5 覯襦 譟一 // jitter螳 豺 float3 worldPosition = ConvertThreadIdToWorldPosition( DTid, dims, jitter );
  • 11. Volumetric Fog 11 蠏碁Μ螻伎覲願る(=豺企朱朱螳讌る) 螻殊給. /* - Global Parameter TemporalAccum : Temporal reprojection 覿, 豌 蟶殊狩 ( 伎 覲願 蠍 覓 ) PrevViewProjectionMatrix : 伎 豺企 */ Texture3D HistoryVolume : register( t0 ); SamplerState HistorySampler : register( s0 ); // ... // Main 企 磯 螻 curScattering = float4( lighting * Intensity * density, density ); if ( TemporalAccum > 0.f ) { float3 worldPosWithoutJitter = ConvertThreadIdToWorldPosition( DTid, dims ); // 伎 UV 螻 float3 prevFrameUV = ConvertWorldPositionToUV( worldPosWithoutJitter, PrevViewProjectionMatrix ); // 0 ~ 1 覯覃 if ( all( prevFrameUV <= ( float3 )1.f ) && all( prevFrameUV >= ( float3 )0.f ) ) { float4 prevScattering = HistoryVolume.SampleLevel( HistorySampler, prevFrameUV, 0 ); curScattering = lerp( prevScattering, curScattering, 0.05f ); } } FrustumVolume[DTid] = curScattering; 磯螻磯螻覲覲朱エれ豢ロ襦給. AccumulatedVolume[pos] = accum; 襯朱蟲企慨覃企れ螻手給. 2) Tricubic texture sampling 覲旧一危一襷覦覲蟆渚蟆朱豢螳誤讌レ詞給. Tricubic texture samplingCUDA Cubic B-Spline Interpolation磯ジ覦朱覲朱エれ襯B-Spline牛企慨螳. 襷覲企る蟆郁骸襯手谿壱 給.
  • 12. Volumetric Fog 12 豢豌: https://twitter.com/FewesW/status/1300045087938879489 蟲一Tricubic sampling 貊襯手誤襦語襷蟆所Fog 螻給. #if TricubicTextureSampling == 1 float4 scatteringColorAndTransmittance = Tex3DTricubic( AccumulatedVolume, AccumulatedVolumeSampler, uv); #else float4 scatteringColorAndTransmittance = AccumulatedVolume.Sample( AccumulatedVolumeSampler, uv ); #endif 襯朱蟲企慨覃企れ螻手給. 襷豺覃 碁Μ殊讌Volumetric Fog蟲蠍磯る伎螻狩蟆るゴ讌給. 覈螳讌螳(Temporal reprojection ろ襭襯 觜襯願危襦)伎讌襷螳企襴磯伎覦朱豢覿危危手螳 . 碁Μ殊蟲豢螳襦危エ覲願苦殊覿企企讌覈螻褐蠍一蠍磯襦蟆給. VolumetricFog.cpp : 貉危語一企襯殊Volumetric Fog 磯螻一れ企. ComputeVolumetricFog() : 螳レ讌. GetVolumetricFogGridSize() : 覲朱エれ蠍郁壱. GetVolumetricFogGridZParams() : Z豢覿朱誤郁壱, 碁Μ殊れ螻手覿襯朱磯ゴ襦Z 豢覿郁啓覃伎覓企伎螳豪蟆覦讌蠍一朱螳.
  • 13. Volumetric Fog 13 VoxelizeFogVolumePrimitives() : Volume 襾誤磯Μ殊牛企襷襴覩誤磯襯朱概伎Volumetric Fog 覲朱エ れ襷. 企ゼ牛企れ覦襯狩給. 蟲螳讌Voxelize 覈螳給. FVolumetricFogLightScatteringCS : 磯螻一惨語一企企れ. FVolumetricFogFinalIntegrationCS : 磯貉危語一企企れ. RenderViewFog() : Fog襯朱襷. FExponentialHeightFogPS : Fog襯朱襷曙一企企れ. 譴觜伎蠍郁讌. 螳誤襦瑚規豌伎github襯殊宛螻覿襴暑. GitHub - xtozero/SSR at volumetric_fog Screen Space Reflection. Contribute to xtozero/SSR development by creating an account on GitHub. https://github.com/xtozero/SSR/tree/volumetric_fog 螳. Reference https://github.com/diharaw/volumetric-fog : opengl 蟲 https://github.com/bartwronski/CSharpRenderer : 蟲 https://github.com/Unity-Technologies/VolumetricLighting/tree/master/Assets/VolumetricFog : Unity蟲