【SIGGRAH 2013】Real Shading in Unreal Engine 4

本文主要內(nèi)容來自于Epic Games Brian Karis在SIGGRAPH 2013上面的分享诵竭,詳情請瀏覽原文

1. Introduction

這里介紹了UE4嘗試將管線升級成PBR的動機榴芳,同時由于整個升級工作都是受Disney在《無敵破壞王》應(yīng)用的PBR材質(zhì)系統(tǒng)[2]的啟發(fā),因此也是以此為基礎(chǔ)開展的鲤嫡,在開始之前泛范,先為UE4的PBR設(shè)定了一系列的目標:

  • Real-Time Performance
  • Reduced Complexity:參數(shù)要夠簡單易用罢荡,且由于場景中天光與直接光照的應(yīng)用都很廣泛区赵,因此這些參數(shù)應(yīng)該能夠同時支持這兩種光照
  • Intuitive Interface:界面直觀
  • Perceptually Linear笼才,對參數(shù)的插值的結(jié)果應(yīng)該等同于對參數(shù)結(jié)果的插值
  • Easy to Master:不需要技術(shù)知識也能理解
  • Robust:足夠穩(wěn)定
  • Expressive:1.基礎(chǔ)shading model要能覆蓋現(xiàn)實世界99%的材質(zhì)骡送;2.所有可分層材質(zhì)(layerable material)都需要共享同一套參數(shù)摔踱,方便插值
  • Flexible:能夠支持non-photorealistic rendering蛹批,方便覆蓋不同風(fēng)格的游戲

2. Shading Model

光照計算公式可以表示成如下形式:

L_o(p, \omega_o) = \int_{\Omega}(k_d\frac{c_{diff}}{\pi} + k_s\frac{D(h)F(v,h)G(l,v,h)}{4(n \cdot l)(n \cdot v)}) L_i(p, \omega_i)n\cdot \omega_i d \omega_i

拆解一下就變成了:
L_o(p, \omega_o) = L_{o_{diff}} + L_{o_{spec}} \\ L_{o_{diff}} = \int_{\Omega}k_d\frac{c_{diff}}{\pi} L_i(p, \omega_i)n\cdot \omega_i d \omega_i \\ L_{o_{spec}} = \int_{\Omega}k_s\frac{D(h)F(v,h)G(l,v,h)}{4(n \cdot l)(n \cdot v)} L_i(p, \omega_i)n\cdot \omega_i d \omega_i

2.1 Diffuse BRDF

這里對比了Burley的漫反射模型跟Lambertian的漫反射模型(公式1)腐芍,發(fā)現(xiàn)其實二者的表現(xiàn)區(qū)別比較小猪勇,沒有必要為了這輕微的提升而浪費因此帶來的計算消耗埠对,且考慮到復(fù)雜的漫反射模型在IBL或者SHL(球諧光照)中的可能無法實現(xiàn)高效渲染,因此這里的漫反射模型就直接取用了最基本的Lambertian Diffuse模型了:

f(l,v) = \frac{c_{diff}}{\pi} ~~~ (1)

c_{diff}指的是像素的基色albedo color弱判。

2.1.1 Microfacet Specular BRDF

經(jīng)典的Cook-Torrance微表面高光著色BRDF模型[4,5]公式給出如下:

f(l,v) = \frac{D(h)F(v,h)G(l,v,h)}{4(n \cdot l)(n \cdot v)} ~~~ (2)

h指的是入射光方l與觀察方向v的中間向量(v = normalize(l+v))昌腰,詳情細節(jié)可以參考[9]。

UE4這邊以Disney的離線渲染模型作為基礎(chǔ)渲染公式捅伤,之后嘗試為公式中的每一項尋找到高效的替代計算方法來進行優(yōu)化丛忆,不過由于每一項內(nèi)容的輸入?yún)?shù)不一致可很,使得效果對比變得困難我抠,下面對每一項進行分開敘述。

Specular D

D表示的是表面法線分布函數(shù)(Normal Distribution Function瓣窄,NDF)康栈,Disney使用的是GGX/Trowbridge-Reitz公式啥么,經(jīng)過測試發(fā)現(xiàn)悬荣,這個公式的性價比非常高氯迂,且如果后面使用Blinn-Phong模型的話嚼蚀,額外的消耗基本上可以忽略轿曙。此外导帝,UE4這邊嘗試用粗糙度的平方來取代Disney公式中的α值:

D(h) = \frac{ \alpha^2 }{ \pi((n \cdot h)^2 * (\alpha^2-1)+1)^2 } ~~~(3)

Specular G

G表示的是幾何表面的微觀細節(jié)對于高光的阻尼作用您单,這一項,UE4取用的是Schlick模型凤优,且為了更好的契合GGX的Smith模型[21]别洪,這里做了一個小改動k = α/2挖垛,這樣一來,對于Schlick模型在α = 1 的時候就跟Smith模型完全一樣了蚕甥,而[0,1]范圍內(nèi)菇怀,這兩者的區(qū)別也比較邪怠(參考Figure 2)呼伸。另外括享,這個地方還參考了Disney為了降低“hotness”而做的簡化處理:將α 用(Roughness + 1) / 2替代(相當于對于D跟G而言铃辖,α 的值是不一樣的娇斩。需要注意的是,這個簡化調(diào)整只會用在分析光源(analytic light source藏否,用公式表達的光源副签,IBL等不屬于此類)上淆储,如果用在IBL上的話本砰,如果用平行于表面的視線渲染的話得到的結(jié)果會過暗:

k=\frac{(Roughness+1)^2}{8}

G_1(v)=\frac{ n\cdot v} {(n \cdot v)(1-k)+k}

G(l,v,h) = G_1(l)G_1(v) ~~~ (4)

Specular F

F表示的是菲涅爾效應(yīng)的對于觀察角度的影響点额,這一項用的是經(jīng)典的Schlick的逼近算法[19]还棱,其中用了SH逼近[10]算法來取代Schlick算法中的指數(shù)power運算珍手,這個修正可以大大降低運算的消耗琳要,同時引起的質(zhì)量下降則可以忽略不計焙蹭,整個公式給出如下:

F(v,h) = F_0+(1-F_0)*2^{(-5.55473*(v \cdot h) -6.98316)*(v \cdot h)} ~~~ (5)

其中F_0指的是光照垂直于平面入射時的反射高光強度拯钻。

Image-Based Lighting


要對IBL應(yīng)用上述的Shading Model粪般,就需要進行輻射度的積分運算亩歹,積分通常都是通過蒙特卡洛算法來模擬:
\int_H L_i(l)f(l,v) cos\theta_ldl \approx \frac{1}{N}\sum_{k=1}^N\frac{L_i(l_k)f(l_k, v)cos\theta_{l_k}}{p(l_k,v)} ~~~~~~(6)

Shader代碼給出如下:

//根據(jù)概率分布函數(shù)計算采樣點
//https://agraphicsguy.wordpress.com/2015/11/01/sampling-microfacet-brdf/
float3 ImportanceSampleGGX( float2 Xi, float Roughness, float3 N )
{
    float a = Roughness * Roughness;
    float Phi = 2 * PI * Xi.x;
    float CosTheta = sqrt( (1 - Xi.y) / ( 1 + (a*a - 1) * Xi.y ) );
    float SinTheta = sqrt( 1 - CosTheta * CosTheta );
    float3 H;
    H.x = SinTheta * cos( Phi );
    H.y = SinTheta * sin( Phi );
    H.z = CosTheta;
    float3 UpVector = abs(N.z) < 0.999 ? float3(0,0,1) : float3(1,0,0);
    float3 TangentX = normalize( cross( UpVector, N ) );
    float3 TangentY = cross( N, TangentX );
    // Tangent to world space
    return TangentX * H.x + TangentY * H.y + N * H.z;
}

float3 SpecularIBL( float3 SpecularColor , float Roughness, float3 N, float3 V )
{
    float3 SpecularLighting = 0;
    const uint NumSamples = 1024;
    for( uint i = 0; i < NumSamples; i++ )
    {
        float2 Xi = Hammersley( i, NumSamples );
        float3 H = ImportanceSampleGGX( Xi, Roughness, N );
        float3 L = 2 * dot( V, H ) * H - V;
        float NoV = saturate( dot( N, V ) );
        float NoL = saturate( dot( N, L ) );
        float NoH = saturate( dot( N, H ) );
        float VoH = saturate( dot( V, H ) );
        if( NoL > 0 )
        {
            float3 SampleColor = EnvMap.SampleLevel( EnvMapSampler , L, 0 ).rgb;
            float G = G_Smith( Roughness, NoV, NoL );
            float Fc = pow( 1 - VoH, 5 );
            float3 F = (1 - Fc) * SpecularColor + Fc;
            // Incident light = SampleColor * NoL
            // Microfacet specular = D*G*F / (4*NoL*NoV)
            // pdf = D * NoH / (4 * VoH)
            SpecularLighting += SampleColor * F * G * VoH / (NoH * NoV);
        }
    }
    return SpecularLighting / NumSamples;
}

而即使通過蒙特卡洛算法來模擬積分運算,依然需要大量的采樣點才能得到較高的顯示質(zhì)量顾稀,通過mipmap[3]可以在一定程度上降低采樣點所需的數(shù)目静秆,不過即使如此對于單個像素而言抚笔,也需要16個以上的采樣點殊橙。而由于為了實現(xiàn)局部反射蛀柴,UE4需要對很多環(huán)境貼圖的采樣結(jié)果進行blend鸽疾,因此這里留給每個像素的預(yù)算只剩下一個采樣點了制肮,16到1豺鼻,這個差距還很明顯儒飒。

Split Sum Approximation

為了進一步降低消耗桩了,這邊做了一個簡化處理井誉,那就是將公式6中的累加運算拆分成兩個累加操作颗圣,而拆分后的這兩個累加都可以通過預(yù)處理的方式計算得到在岂,這樣在運行時蔽午,只需要一次采樣祠丝,即可得到對應(yīng)的計算結(jié)果写半。至于這樣的拆分是否合理呢叠蝇,實際上悔捶,在L_i(l)是一個常量的時候,這個拆分是無損等價拆分犁柜,在其他情況下馋缅,其計算結(jié)果也非常的接近萤悴,因此這種拆分是可以說得過去的:
\frac{1}{N}\sum_{k=1}{N}\frac{L_i(l_k)f(l_k, v) cos \theta_{l_k}}{p(l_k, v)} \approx(\frac{1}{N}\sum_{k=1}^N L_i(l_k))(\frac{1}{N}\sum_{k=1}^N\frac{f(l_k,v)cos\theta_{l_k}}{p(l_k, v)}) ~~~~~~~~~(7)

Pre-Filtered Environment Map
具體推導(dǎo)可以參考Specular IBL

第一個累加項表示的是各個方向的光照輸入的情況费薄。這里將第一個累加公式通過預(yù)處理的方式計算各個不同粗糙度輸入下的輸出义锥,并將結(jié)果存儲到一張mipmap cubemap中拌倍,這是游戲行業(yè)的標準做法[1,9]柱恤,與之不同的是梗顺,UE4這里存儲的是Shading Model的GGX分布與環(huán)境貼圖的卷積結(jié)果寺谤,這個卷積也是通過蒙特卡洛算法計算得到变屁。由于這里表述的是微表面模型疮胖,因此shading model的GGX的分布與觀察角度是有關(guān)系的澎灸,為了簡化計算性昭,這里假設(shè)視線與法線的夾角為0糜颠,即n = v = r括蝠。而這個假設(shè)會導(dǎo)致以平行于表面的視線來查看場景時忌警,將無法得到清晰的鏡面反射(lengthy reflection)法绵,跟前面Split Sum Approximation的拆分簡化處理不同朋譬,這個地方的簡化算法會有比較大的損害徙赢,這也是為什么UE4的IBL輸出表現(xiàn)誤差大的主要原因狡赐。下面給出具體的實現(xiàn)代碼枕屉,需要注意的是搀擂,里面的權(quán)重計算公式用的是cos(θlk)哨颂,因為實際測試中發(fā)現(xiàn)咆蒿,這個權(quán)重計算公式得到的效果更好沃测,這個數(shù)值在上面的公式中沒有體現(xiàn)出來蒂破。

float3 PrefilterEnvMap( float Roughness, float3 R )

{

    float3 N = R;

    float3 V = R;

    float3 PrefilteredColor = 0;

    const uint NumSamples = 1024;

    for( uint i = 0; i < NumSamples; i++ )

    {

        float2 Xi = Hammersley( i, NumSamples );

        float3 H = ImportanceSampleGGX( Xi, Roughness, N );

        float3 L = 2 * dot( V, H ) * H - V;

        float NoL = saturate( dot( N, L ) );

        if( NoL > 0 )

        {

            PrefilteredColor += EnvMap.SampleLevel( EnvMapSampler , L, 0 ).rgb * NoL;

            TotalWeight += NoL;

        }

    }

    return PrefilteredColor / TotalWeight;

}

Environment BRDF

第二項是除了光照之外的其他數(shù)據(jù)惧互,也可以看成是高光BRDF在白光(L_i(lk) = 1)輸入下的輸出喊儡,將Schlick的菲涅爾公式帶入其中的話:F(v, h) = F0 + (1 ? F0)(1 ? v · h)^5前面的積分可以展開成一個積分運算:
\int_H f(l,v)cos \theta_l dl = F_0 \int_H \frac{f(l, v)}{F(v,h)}(1-(1-v \cdot h)^5) cos \theta_l dl + \int_H \frac{f(l,v}{F(v,h)}(1-v \cdot h)^5 cos \theta_l dl ~~~~~~~~~~~~~~(8)

這個公式可以表示成兩個輸入下的兩個輸出艾猜,其中兩個輸入指的是粗糙度Roughness(這個對應(yīng)的是f(l,v)?)以及cosθv(這個對應(yīng)的是v*h)匆赃,兩個輸出對應(yīng)的是等式右邊的F0的scale因子A與bias因子B算柳,F(xiàn)0 * A + B瞬项。兩輸入兩輸出可以編碼成一個2D的LUT:

這個LUT使用的像素格式為R16G16(保證有足夠的精度滥壕,不然表現(xiàn)會有比較大的誤差)绎橘。

做完上述的處理之后称鳞,跟同行們的實現(xiàn)進行對比發(fā)現(xiàn)冈止,其實大家給出的解決方案最終都殊途同歸——使用LUT來進行簡化——只有Lazarov走得更遠了一步[11]熙暴,他提出了一種對于積分公式的簡化模擬公式周霉。

float2 IntegrateBRDF( float Roughness, float NoV )
{
    float3 V;
    V.x = sqrt( 1.0f - NoV * NoV ); // sin
    V.y = 0;
    V.z = NoV; // cos
    float A = 0;
    float B = 0;
    const uint NumSamples = 1024;
    for( uint i = 0; i < NumSamples; i++ )
    {
        float2 Xi = Hammersley( i, NumSamples );
        float3 H = ImportanceSampleGGX( Xi, Roughness, N );
        float3 L = 2 * dot( V, H ) * H - V;
        float NoL = saturate( L.z );
        float NoH = saturate( H.z );
        float VoH = saturate( dot( V, H ) );
        if( NoL > 0 )
        {
            float G = G_Smith( Roughness, NoV, NoL );
            float G_Vis = G * VoH / (NoH * NoV);
            float Fc = pow( 1 - VoH, 5 );
            A += (1 - Fc) * G_Vis;
            B += Fc * G_Vis;
        }
    }
    return float2( A, B ) / NumSamples;
}

float3 ApproximateSpecularIBL( float3 SpecularColor , float Roughness, float3 N, float3 V )
{
    float NoV = saturate( dot( N, V ) );
    float3 R = 2 * dot( V, N ) * N - V;
    float3 PrefilteredColor = PrefilterEnvMap( Roughness, R );
    float2 EnvBRDF = IntegrateBRDF( Roughness, NoV );
    return PrefilteredColor * ( SpecularColor * EnvBRDF.x + EnvBRDF.y );
}

Figure 4: 第一排是參考, 中間一排是split sum approximation, 下面一排是完整的模擬 n = v 国瓮。雖然因為徑向?qū)ΨQ的假設(shè)引入了較多的誤差乃摹,不過加上其他部分整合后的輸出結(jié)果跟參考輸出其實就沒有太多的差別了孵睬。

Figure 5: 這是一組絕緣體的輸出對比

上面這里的Split-sum Approximation是天光Specular部分肪康,天光Diffuse部分同樣需要進行預(yù)處理
L_{o_{diff}} = \int_{\Omega}k_d\frac{c_{diff}}{\pi} L_i(p, \omega_i)n\cdot \omega_i d \omega_i = \\ k_d\frac{c_{diff}}{\pi} \int_{\Omega}L_i(p, \omega_i)n\cdot \omega_i d \omega_i

積分部分為當前采樣點的法線的上半球的采樣結(jié)果積分磷支,輸入為法線與environment cubemap雾狈,可以通過預(yù)計算完成善榛,這個預(yù)計算是一個convolution過程移盆,預(yù)計算結(jié)果我們稱之為irradiance map(詳情可參考Diffuse irradiance):

Material Model


UE4所使用的材質(zhì)模型,實際上是在Disney材質(zhì)模型的基礎(chǔ)上以實時渲染為目標經(jīng)過一系列的優(yōu)化處理后而來的绞愚。通過限定材質(zhì)的參數(shù)以優(yōu)化G-Buffer的空間消耗位衩,降低貼圖存儲空間消耗以及縮小多層材質(zhì)的混合消耗糖驴。

基礎(chǔ)的材質(zhì)模型主要包含以下輸入貼圖:

  • 基色貼圖
  • 金屬度貼圖,整合導(dǎo)體跟絕緣體
  • 粗糙度貼圖
  • 孔洞貼圖Cavity俺榆,用于模擬微表面的陰影表現(xiàn)

前三張貼圖都跟Disney的材質(zhì)模型一致,只有孔洞貼圖是UE4引入的抑诸,這個貼圖主要用于模擬模型幾何表面的微觀凹凸感蜕乡,比如衣服上的褶皺层玲,水泥磚上的孔洞等辛块,這些表面細節(jié)通常用法線貼圖來表征润绵,但是法線貼圖不會產(chǎn)生對應(yīng)的陰影尘盼,因此需要增加一張額外的貼圖處理這個問題卿捎。

這里需要注意的是午阵,UE4的材質(zhì)貼圖中沒有了高光貼圖Specular底桂,這是因為戚啥,Karis覺得高光貼圖這個名字很容易讓人誤會,而且也不方便實現(xiàn)美術(shù)同學(xué)從高光強度intensity控制到粗糙度roughness控制的轉(zhuǎn)變览濒。此外贷笛,其默認值應(yīng)該是0.5乏苦,而美術(shù)同學(xué)以及引擎程序們卻經(jīng)常好像忘了這一點汇荐,都會以1作為其默認值掀淘。而因為高光貼圖應(yīng)用的場景大多是為了計算小尺寸陰影革娄,且Karis發(fā)現(xiàn)折射系數(shù)(index of refraction, IOR)變量對于非金屬而言其實沒有什么作用拦惋,因此決定將高光貼圖替換成更為通俗易懂的孔洞貼圖。非金屬材質(zhì)的F0目前給的是一個0.04的常量吞彤。

Disney的材質(zhì)模型中還有一些參數(shù)并沒有被納入UE4的基礎(chǔ)材質(zhì)模型饰恕,這是因為這些參數(shù)其實只有在特殊場合中才會用到埋嵌,因此只需要通過一些特殊的方式來處理即可:

  • 次表面貼圖:用于對Shadow map進行區(qū)別采樣
  • 各向異性貼圖:需要采樣較多的IBL sample
  • Clearcoat貼圖:需要對IBL進行雙重采樣
  • Sheen:光澤貼圖

在UE4中雹嗦,除了次表面貼圖在《Elemental》Demo中用于進行冰面模擬之外了罪,其他的參數(shù)到目前為止還沒用過泊藕。目前UE4使用的是單純的延遲渲染管線娃圆,不同的shading model在G-Buffer中對應(yīng)的是不同的Shading Model ID讼呢,以用于進行不同的Shader分支處理悦屏,未來如果支持了前向渲染础爬、延遲渲染混合管線之后,再考慮支持更多特殊的shading model获搏。

Experiences

在實際使用的時候,由于高光貼圖已經(jīng)被替換成了孔洞貼圖碱茁,因此美術(shù)同學(xué)需要調(diào)整粗糙度貼圖來實現(xiàn)對高光效果的調(diào)整纽竣,不過需要注意的是蜓氨,高光貼圖中穴吹,數(shù)值越大嗜侮,表明顏色的高亮程度越高锈颗,但是對于粗糙度貼圖而言击吱,數(shù)值越大就表示粗糙度越高覆醇,其對應(yīng)的高光程度反而越低,這是需要注意的柴罐。

金屬度貼圖中存儲的金屬度并不是0/1二值的凿试,而是[0,1]的浮點范圍那婉,而且在使用中注意不要設(shè)置為0或者1详炬,因為自然界中沒有完全反射也沒有完全不反射的物質(zhì)寞奸。

在從非PBR到PBR轉(zhuǎn)型的過程中枪萄,UE4還遭遇了一些問題瓷翻,比如說在開發(fā)《堡壘之夜》的時候遇到的一個問題:《堡壘》是一個比較風(fēng)格化的游戲齐帚,整個游戲的風(fēng)格比較偏動畫对妄,non-photorealistic饥伊,為了實現(xiàn)這種效果琅豆,在開發(fā)之初就為diffuse/specular反射設(shè)定了一套互補的顏色數(shù)據(jù)茫因,而這種設(shè)定是物理不正確的,因此無法使用上面提到的PBR材質(zhì)模型盛嘿,且由于開發(fā)日久次兆,已經(jīng)不太適合推倒重來芥炭,因此又專門為堡壘保留了老式的diffuse/specular材質(zhì)模型园蝠,不過這并不意味著新的材質(zhì)模型不支持動畫風(fēng)格的游戲彪薛,實際上Disney的《無敵破壞王》就是使用的PBR實現(xiàn)的動畫電影善延。

Material Layering

分層材質(zhì)系統(tǒng)的通過對多個source材質(zhì)進行混合來實現(xiàn)不同的材質(zhì)效果挚冤,而source材質(zhì)則是來源于一個共享的材質(zhì)庫赞庶。UE以前的材質(zhì)系統(tǒng)需要為每一個模型指定其專有的材質(zhì)歧强,而這個專有的材質(zhì)的參數(shù)又是通過專有的貼圖來指定摊册,相對于以前的材質(zhì)系統(tǒng)茅特,UE4的新的分層材質(zhì)系統(tǒng)有很多便利的地方:

  • 可以在多個asset中共享材質(zhì)來減少重復(fù)勞動
  • 對于單個asset而言白修,其材質(zhì)的實現(xiàn)與指定也更為方便簡單
  • 為整個游戲?qū)崿F(xiàn)一套歸一的材質(zhì)標準

為了適應(yīng)分層貼圖系統(tǒng)兵睛,UE4這邊的工具系統(tǒng)就需要做相應(yīng)的改進笛丙,因此在UE3早期的時候就開發(fā)了藍圖節(jié)點編輯系統(tǒng)假颇,通過藍圖編輯的材質(zhì)最終都會轉(zhuǎn)換成shader代碼笨鸡。

為了將分層材質(zhì)集成到現(xiàn)有的工作流上镜豹,特地引入了一個新的數(shù)據(jù)結(jié)構(gòu):材質(zhì)attributes,通過這個數(shù)據(jù)類型泰讽,材質(zhì)layer可以用作節(jié)點編輯的輸入進行l(wèi)ayer之間的組合與運算已卸,事實證明累澡,這種做法簡化了材質(zhì)的編輯愧哟。

由于材質(zhì)參數(shù)只有寥寥幾個蕊梧,因此材質(zhì)的混合可以直接在一個shader中完成腮介,不過這種實現(xiàn)方式對于那些將一個模型拆分成多個部分進行渲染來說叠洗,可能會存在問題灭抑。

分層材質(zhì)系統(tǒng)上線之后名挥,到目前為止收到的反饋都是正面的,既提高了質(zhì)量也提高了效率榄融,未來可能會考慮開發(fā)離線的材質(zhì)系統(tǒng)以支持更大范圍的材質(zhì)層數(shù)以及更好的可擴展性愧杯。

Figure 8: Material layering results exploiting multiple frequencies of detail

Lighting Model


提升光照模型的表現(xiàn)的兩個核心點:光照衰減(light falloff)以及面光源(non-punctual light source of emission)耍铜。

光照衰減要想表現(xiàn)正確就要遵循物理定律棕兼,實現(xiàn)起來就需要滿足兩個條件:

  1. 光照強度與到光源的距離的平方成反比(能量守恒)
  2. 光照強度使用真實的物理光照強度(現(xiàn)實世界測度計所測量得到的數(shù)值)

在這里有一個問題是伴挚,按照第一個條件來實施的話茎芋,任何距離上的點受到的光照都不會降低至0田弥,從而導(dǎo)致整個場景中無窮遠處的位置也將受到光照的影響铡原,十分影響實施效率眷蜈,這個問題有很多解決辦法[4]酌儒,UE4采用的是一種窗口方法忌怎,即在光源的主要影響范圍的光照強度的計算公式不受影響榴啸,繼續(xù)按照半徑的平方的反比來晚岭,而超出這個范圍之外的光照強度則是采用一個軟過渡的方式來降低至0.這種方法的優(yōu)點在于,修改了光源的半徑狂鞋,并不會改變其有效的亮度——保證有效的亮度不改變對于被美術(shù)同學(xué)鎖定的情況而言是非常重要的骚揍,但是出于對性能的考慮就需要修正光照的范圍信不。

falloff = \frac{saturate(1-(distance/lightRadius)^4)^2}{{distance^2}+1} ~~~~~~~~~(9)

分母中的1是為了避免distance為0的時候的無窮大抽活,對于那些不需要物理正確的渲染風(fēng)格的游戲而言酌壕,這個數(shù)值可以暴露給美術(shù)同學(xué)進行控制卵牍。加了上面這個公式控制之后糊昙,對于那些擁有大量局部光源的場景而言释牺,其表現(xiàn)與期望的點光表現(xiàn)效果基本上也沒什么區(qū)別了没咙。

通過對UE源碼的分析祭刚,我們發(fā)現(xiàn)涡驮,實際上UE在使用的時候是直接移除上述公式中的分母項捉捅,而僅僅保留了分子項棒口,下面給出falloff公式與InverseSquare公式的表現(xiàn):

InverseSquare = saturate(1-(distance/lightRadius)^4)^2

FallOff = saturate(1-(distance/lightRadius)^2)^{FallOffExp}, FallOffExp_Default = 8

Green:InverseSquare, Blue:Falloff

上述截圖中剥懒,虛線表示的是純分子表現(xiàn)初橘,實線表示的是添加了二次分母的表現(xiàn),從效果對比來看充岛,兩者區(qū)別不大保檐,可能這也是為什么UE只保留了分母的原因吧?

Area Lights


面光源的重要性不僅僅在于能夠生成更為真實的場景畫面崔梗,更在于能夠讓美術(shù)同學(xué)能夠無拘無束的使用PBR材質(zhì)夜只。如果不能實現(xiàn)正確的面光源效果,美術(shù)同學(xué)都不敢使用過于低粗糙度的材質(zhì)蒜魄,反射的作用使得低粗糙度的表面表現(xiàn)得就像一個面光源扔亥,在面光源渲染不正確的情況下會使得畫面表現(xiàn)非常的不自然,而如果需要為不同的光源單獨設(shè)置不同的材質(zhì)又違背了PBR在任何光源環(huán)境下都應(yīng)該表現(xiàn)正確的原則谈为。

光源面光源的實現(xiàn)粘茄,目前有很多人在研究。在離線渲染中,最通用的做法就是將面光源表達成一個點光源陣列[12,20]磺平。而這種做法對于實時渲染來說是不現(xiàn)實的,下面先給出UE4對于面光源實施效果的一些期望:

  • Consistent material appearance乙埃,使用光滑的材質(zhì)甫何,經(jīng)過面光源照射后的結(jié)果應(yīng)該也是光滑的
  • Approaches point light model as the solid angle approaches zero,將面光源縮小到一點時巍耗,得到的效果應(yīng)該跟點光源的效果一致
  • Fast enough to use everywhere驯耻,高效

Billboard Reflections

公告板反射[13]其實是一種可以當成離散光源的IBL,一個存儲了自發(fā)光數(shù)據(jù)的2D貼圖可以映射到3D場景中的一個矩形上女气。跟環(huán)境貼圖的預(yù)處理一樣,這個自發(fā)光貼圖也會對不同尺寸的specular distribution cone進行預(yù)處理。而計算這個自發(fā)光貼圖輸出的高光,在cone的形狀接近于高光NDF的時候观游,可以看成是某種形式的cone tracing。

cone tracing的簡單介紹如下:


首先聋丝,在每個表面的每個點上,將傳統(tǒng)做GI計算時的半球積分空間給分割成多個獨立的Cones,用這些Cones組合得到的空間(中間會有重疊或裂隙)來近似原始的半球空間火惊,并在其上做Irridiance的采集宴倍。


之后,對于每個獨立的Cone,又使用下述方法再進行近似:

也即是在每個Cone的內(nèi)部又將其用多個密布排列的Cube來進行近似,使用Cube的方法是其會使得OCTree的Tracing變得很方便。 每個Cube大小的計算就可以根據(jù)具體Cone的屬性(比如夾角辞居,最大長度等)來進行計算抱完,一般來說從每個Cone內(nèi)部分割出來的Cube個數(shù)不會太多.
對于每個Cube在OCTree中的Tracing捅僵,使用的方法也比較簡單:直接計算出的Cube的Size,然后根據(jù)此Size找出與其最適配的那層Mipmap,這里的原則就是Cube的Size要盡可能地與Mipmap層中的結(jié)點Size接近。最后惕蹄,直接使用此Cube的位置信息來采樣Mipmap中的相應(yīng)位置上的結(jié)點值泪蔫,即可完成對此Cube的Tracing婿滓。
對Cone中的每個Cube完成Tracing之后卿吐,當前Cone方向上的Irridiance累積結(jié)果就可以認為是Cone中所有Cube采樣結(jié)果的疊加。這個看起來雖然有些不太合理,但是視覺效果上的近似已經(jīng)很不錯了。此外,作者也對該近似方法進行了數(shù)學(xué)上的分析(step by step pre-integration):將每個Cube認為是Transparent屬性,然后Irridiance會在其中進行不斷的傳遞。具體可以見這論文里邊的詳細內(nèi)容。
原文鏈接:https://blog.csdn.net/bugrunner/article/details/8962535


cone(從受光點發(fā)出)中心點的射線將會與公告板所在的平面存在一個交點,而這個點在屏幕空間中的位置信息則被用作貼圖的坐標,交點處對應(yīng)的cone圓面的半徑則被用于推導(dǎo)對應(yīng)的specular cone預(yù)處理的mip層級。不幸的是,雖然這種方法能夠用一種非常直觀的方法來實現(xiàn)對復(fù)雜面光源的模擬,但是卻無法滿足前面剔除的第二個條件(固體角接近0的時候其效果要與點光源保持一致):

  • 由于自發(fā)光貼圖的預(yù)處理過程是在一個平面上完成的双饥,因此其能夠表達的固體角是受限的(無法表示背面的固體角迟螺?)
  • 在cone中心的射線與平面無交點的時候排霉,沒有輸出數(shù)據(jù)
  • 這個模型中的光照向量l是未知的或者說只能用反射光線方向來近似瑰钮。

Cone Intersection

cone tracing的結(jié)果可以通過代數(shù)運算的方式得到苟耻,不需要提前預(yù)處理智蝠。cone跟sphere的相交檢測可以通過Oat的cone-cone相交檢測算法[15]求得颈嚼,不過這種方法消耗過高,不適合用于實時渲染,這個方法的一個替代算法是Drobot[7]提出的,這種方法可以用一個朝向shading point的圓盤(disk)來實現(xiàn)跟cone的相交檢測。之后對于相交區(qū)域,再用一個能夠近似高光NDF的多項式逐段逐段進行積分即可。

如果使用Drobot算法,cone跟disk的相交區(qū)域就會是一個徑向?qū)ΨQ的區(qū)域,這種對稱區(qū)域?qū)τ阡秩灸切├旌蟮母吖猓╯tretched highlights)就無能為力了,而這種拉伸高光是微表面高光模型中的一個重要特征。另外跟公告板反射一樣,用這種算法得到的shading model也沒有對應(yīng)的light vector。

Specular D Modification

UE4在2012年提出的一種實現(xiàn)方法[14]就是根據(jù)光源的固體角來修正高光的distribution寨蹋。其實現(xiàn)原理就是將光源的distribution看成光源固體角的D(h)項(Specular Normal Distribution Function)运褪,在這個理論的基礎(chǔ)下璃诀,兩個Specular Distribution的卷積就可以用將這二者對應(yīng)的cone的夾角相加得到的新的cone所對應(yīng)的Specular Distribution來近似。

具體而言,就是將公式3中的α 值轉(zhuǎn)換成一個cone angle,將這個角度跟光源對應(yīng)的固體角相加,再轉(zhuǎn)換回公式3中的α 值,這個過程可以用如下的公式來模擬:

\alpha^{'} = satuarate(\alpha + \frac{sourceRadius}{2*distance})

雖然這個實現(xiàn)算法非常高效,但是其不符合前面對于面光源的三點要求中的第一點(Consistent material appearance),因為對于光滑的材質(zhì)在使用大的面光源照射的時候源梭,得到的效果卻是粗糙的(從上面的公式可以看出脑溢,當sourceRadius很大的時候社牲,不管α 是否為0熟空,新計算的粗糙度都會比較大)迈喉。雖然存在瑕疵得运,但是這個模型在高光的NDF比較緊湊(啥意思瞬女?能量比較集中?)的時候(比如說Blinn-Phong高光模型)表現(xiàn)非常好宝穗,不過對于UE4所選用的GGX Shading Model布卡,這種算法的效果就不是很好了贸街。

Figure 10:左圖參考, 右圖specular D modification方法效果,可以看到對于高光的模擬做得不是很好

Representative Point

如果我們能夠直接以面光源上的一個點的輸出來代替面光源的整個輸出的話渐白,那么UE4之前的點光Shading Model就可以直接應(yīng)用了襟诸,面光源上的這個點就被稱為representative point陷揪,這個點的選取通常是依照最大貢獻值來確定,比如說,對于Phong distribution而言,通常會選取距離反射光線最近的那一點作為representative point。

這個方法曾經(jīng)在文獻[16][22]中被提到叔壤,不過其效果并不符合能量守恒定律俺亮,雖然通過移動光源的原點(origin of emitted light)本讥,可以增加光源的固體角從而減輕問題但無法完全消除撞芍。想要完全的修正這個問題會比較復(fù)雜,因為輸出能量的差異對于不同的材質(zhì)是不一樣的,比如說,對于一個粗糙的模型而言动看,調(diào)整輸入光的方向?qū)τ谳敵瞿芰縼碚f可能影響不大仇轻,而對于一個光滑的模型而言方淤,其輸出的能量的改變就非常的明顯了。

下面看下不同的光源應(yīng)用這種方法的具體實施方案。

Sphere Lights

球面光源的輻射照度(Irradiance)在光源球體高于水平面(horizon)的時候等同于點光源的輻射照度[18],雖然這個結(jié)論并不直觀,但是大大減少了我們的計算量:如果我們能夠接受光源球體沉入到水平線以下位置的誤差的話,那么我們在實際計算中就只需要著重考慮高光部分即可。

查找與反射向量(結(jié)合下文來看,這個地方的反射向量應(yīng)該指的是View Dir的反射向量)具有最小夾角的點(這里查找的點是否就是可以用于替代整個球面光源的點光源的點醇疼?)就等同于查找到這個反射向量的距離最小的點普监,其公式給出如下:

centerToRay = L-(L\cdot r)r\\ closestPoint = L+centerToRay*saturate(\frac{sourceRadius}{|centerToRay|}) \\ I = ||closestPoint||

其中L指的是從當前著色點到光源中心的向量,而sourceRadius就是光源的半徑,r指的是反射向量,centerToRay指的是從球心向著r引出的垂線的方向,注意上面的saturate是為了應(yīng)對反射光線與球體相交的情況,這個時候的closestPoint就不是球面上的點,而是光源中心到反射光線上的最近一點了讳嘱。

通過將光源的原點從球心移動到球面钝鸽,可以有效的拓寬高光的distribution范圍财岔,雖然這個地方處理的并不是微表面distribution夷恍,但還是可以借用Phong Specular Distribution公式來解釋:

I_{point} = \frac{p+2}{2\pi} cos^P \phi_r ~~~~~~~ (12)\\ I_{sphere} = \left\{ \begin{matrix}\frac{p+2}{2\pi} ~~ if ~ \phi_r < \phi_s\\ \frac{p+2}{2\pi}cos^P(\phi_r - \phi_s) ~~ if ~ \phi_r < \phi_s \end{matrix} \right\} ~~~~~~~ (13)

其中?r 是r跟L之間的夾角(在Phong高光公式中唠梨,這個夾角應(yīng)該是R跟V之間的夾角)磺芭,而是?s 球面包角(目測是從當前的著色點向著球體引兩條切線,這兩條切線的夾角,就是包角)的一半,公式12是經(jīng)過歸一化處理的劫谅,即對于球面積分得到的結(jié)果應(yīng)該等于1戴尸,而公式13則是非歸一化的了挎峦,而且由于指數(shù)p的存在峭咒,其積分的結(jié)果可能比1大很多。

為了保證能量守恒贡定,即公式13的積分結(jié)果等于1步悠,就需要對公式進行一個處理,整個實現(xiàn)過程類似于前面Specular D中為了應(yīng)對distribution范圍增大而做的處理一樣,即為公式13重新設(shè)計一個歸一化的因子。對于GGX而言盔腔,這個歸一化因子是

\frac{1}{\pi \alpha^2}

因此這里歸一化的做法就是將原有的歸一化因子除以新的distribution范圍的歸一化因子灯荧,得到的歸一化因子等于如下公式:

SphereNormalization = (\frac{\alpha}{\alpha^{'}})^2 ~~~~~~(14)

從結(jié)果上來看,球面代表點方法符合前面給出的所有條件:能夠滿足能量守恒定律漩勤,不管光源類型是什么置谦,都能夠得到正確的一致的表現(xiàn)。光滑的材質(zhì)渲染的結(jié)果也是光滑的敏晤,而且由于這個做法只會改動到BRDF的輸入數(shù)據(jù)耗拓,整個Shading Model是不受影響的黄锤,而且這種算法的實現(xiàn)非常的高效。(這個算法只適用于球面光源)

Figure 12: 左邊參考, 右邊是Representative point方法的結(jié)果僵控,雖然能量守恒上并不完美,但是跟參考的結(jié)果已經(jīng)相差不遠了

Tube Lights

球面光源比較適合模擬那些燈泡類型的光源,而現(xiàn)實世界中最常見的熒光燈則比較適合使用膠囊狀的燈管光源(tube light)來模擬辕狰。為了簡化處理默勾,最開始這里先處理一下只有長度而沒有半徑的線光源(radius = 0)。高于水平面horizon的線光源的輻射照度Irradiance可以通過公式積分得到[16,17]:

\int_{L_0}^{L_1}\frac{n \cdot L}{|L|^3}dL = \frac{\frac{n \cdot L_0}{|L_0|} + \frac{n \cdot L_1}{|L_1|}}{|L_0||L_1|+(L_0 \cdot l_1)} ~~~~~ (15)

其中等限,L_0L_1指的是從著色點到線光源的兩個端點的向量癣缅。

為了避免得到負數(shù)irradiance直晨,或者分母為0的情況,同時考慮到當線光源的長度過渡到0的時候irradiance也應(yīng)該衰減到0的合理推斷,這里需要對上面的公式做一下修正:[圖片上傳失敗...(image-329acb-1594972357212)]

irradiance = \frac{2*saturate(\frac{n \cdot L_0}{|2L_0|} + \frac{n \cdot L_1}{|2L_1|})}{|L_0||L_1| + (L_0 \cdot L_1) + 2} ~~~~ (16)

對于線光源的高光部分咖气,就需要從下面的公式中求出 t 來:

L_d = L_1 - L_0 \\ I = ||L_0 + saturate(t)L_d|| ~~~~ (17)

Picott[16]給出的與反射向量r的夾角最小的點所對應(yīng)的t值計算公式如下所示:

t = \frac{(L_0 \cdot L_d) (r \cdot L_0) - (L_0 \cdot L_0)(r \cdot L_d)}{(L_0 \cdot L_d) (r \cdot L_d) - (L_d \cdot L_d)(r \cdot L_0)} ~~~~ (18)

跟球面光源一樣乳幸,這里通過用最近距離來模擬最小角度:
t = \frac{(r \cdot L_0)(r \cdot L_d) - (L_0 \cdot L_d)}{|L_d|^2 - (r \cdot L_d)^2} ~~~~~~~~~~~~~ (19)

公式19的計算消耗更低,且其計算結(jié)果跟公式18的計算結(jié)果也非常逼近闽颇,不過這個公式由于有一些邊界情況處理得不到位,導(dǎo)致并不是所有時候都能找到對應(yīng)的最近點您宪。

這里需要注意的是极祸,由于公式18跟19都是將r當成一條直線而非一條射線來對待(直線沒有端點,射線有一個端點),因此都沒有考慮射線指向遠離光源方向的情況,從而導(dǎo)致在射線方向從指向光源向著遠離光源角度過渡的時候,出現(xiàn)結(jié)果從某個端點跳變到另一個端點的情況茅逮,這個問題雖然可以通過將計算結(jié)果與兩個端點進行比對來修復(fù),不過這種修復(fù)方式性價比太低,因此最終選擇接受這個瑕疵的存在窍箍。

為了保證能量守恒,這里也采用跟球面光源一樣的處理方式剑令,不過由于這個地方只有一個維度,因此這里取用的是各向異性的GGX[2]钾埂,各向異性GGX的歸一化因子是

\frac{1}{\pi \alpha_x \alpha_y}

(對于各向同性GGX有,αx = αy = α),得到新的歸一化因子:
LineNormalization = \frac{\alpha}{\alpha^{ '}}

因為上述的操作只包括對光源原點進行移動竣灌,并在這個基礎(chǔ)上增加一個能量守恒的處理驻龟,所以可以通過累加來進行tube light的模擬。通過將線光源跟球面光源進行卷積處理,能夠很好的模擬tube light的效果洒琢,其結(jié)果圖13所示:

Figure 13: Tube light using the representative point method with energy conservation

經(jīng)過驗證發(fā)現(xiàn)汪厨,使用Representative Point方法加上能量守恒修正能夠?qū)崿F(xiàn)對簡單形狀的面光源的高效模擬,以后可能會將這個方法推廣到更多更復(fù)雜光源的實現(xiàn)上采盒,尤其是textured quad光源除盏,以實現(xiàn)復(fù)雜的多種顏色的光源。

Conclusion


經(jīng)過上面的一些處理后逞壁,UE4在Shading效果,材質(zhì)系統(tǒng)以及光源模擬上得到了很好的效果蟋恬。

Bibliography


[1] AMD, CubeMapGen: Cubemap Filtering and Mipchain Generation Tool.

[2] Burley, Brent, “Physically-Based Shading at Disney”, part of “Practical Physically Based Shading
in Film and Game Production”, SIGGRAPH 2012 Course Notes.

[3] Colbert, Mark, and Jaroslav Krivanek, “GPU-based Importance Sampling”, in Hubert Nguyen,
ed., GPU Gems 3, Addison-Wesley, pp. 459–479, 2007.

[4] Coffin, Christina, “SPU Based Deferred Shading in Battlefield 3 for Playstation 3”, Game
Developers Conference, March 2011.

[5] Cook, Robert L., and Kenneth E. Torrance, “A Reflectance Model for Computer Graphics”,
Computer Graphics (SIGGRAPH ’81 Proceedings), pp. 307–316, July 1981.

[6] Cook, Robert L., and Kenneth E. Torrance, “A Reflectance Model for Computer Graphics”,
ACM Transactions on Graphics, vol. 1, no. 1, pp. 7–24, January 1982.

[7] Drobot, Micha l, “Lighting Killzone: Shadow Fall”, Digital Dragons, April 2013.

[8] Gotanda, Yoshiharu, “Practical Implementation of Physically-Based Shading Models at tri-Ace”,
part of “Physically-Based Shading Models in Film and Game Production”, SIGGRAPH 2010
Course Notes.

[9] Hoffman, Naty, “Background: Physics and Math of Shading”, part of “Physically Based Shading
in Theory and Practice”, SIGGRAPH 2013 Course Notes.

[10] Lagarde, S′ebastien, “Spherical Gaussian approximation for Blinn-Phong, Phong and Fresnel”,
June 2012.

[11] Lazarov, Dimitar, “Getting More Physical in Call of Duty: Black Ops II”, part of “Physically
Based Shading in Theory and Practice”, SIGGRAPH 2013 Course Notes.

[12] Martinez, Adam, “Faster Photorealism in Wonderland: Physically-Based Shading and Lighting
at Sony Pictures Imageworks”, part of “Physically-Based Shading Models in Film and Game Production”,
SIGGRAPH 2010 Course Notes.

[13] Mittring, Martin, and Bryan Dudash, “The Technology Behind the DirectX 11 Unreal Engine
Samaritan Demo”, Game Developer Conference 2011.

[14] Mittring, Martin, “The Technology Behind the Unreal Engine 4 Elemental demo”, part of “Advances
in Real-Time Rendering in 3D Graphics and Games Course”, SIGGRAPH 2012.

[15] Oat, Chris, “Ambient Aperture Lighting”, SIGGRAPH 2006.

[16] Picott, Kevin P., “Extensions of the Linear and Area Lighting Models”, Computers and Graphics,
Volume 12 Issue 2, March 1992, pp. 31-38.

[17] Poulin, Pierre, and John Amanatides, “Shading and Shadowing with Linear Light Sources”,
IEEE Computer Graphics and Applications, 1991.

[18] Quilez, Inigo, “Spherical ambient occlusion”, 2006.

[19] Schlick, Christophe, “An Inexpensive BRDF Model for Physically-based Rendering”, Computer
Graphics Forum, vol. 13, no. 3, Sept. 1994, pp. 149–162.

[20] Snow, Ben, “Terminators and Iron Men: Image-based lighting and physical shading at ILM”,
part of “Physically-Based Shading Models in Film and Game Production”, SIGGRAPH 2010
Course Notes

[21] Walter, Bruce, Stephen R. Marschner, Hongsong Li, Kenneth E. Torrance, “Microfacet Models
for Refraction through Rough Surfaces”, Eurographics Symposium on Rendering (2007), 195–206,
June 2007.

[22] Wang, Lifeng, Zhouchen Lin, Wenle Wang, and Kai Fu, “One-Shot Approximate Local Shading” 2006.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子肌稻,更是在濱河造成了極大的恐慌,老刑警劉巖芥吟,帶你破解...
    沈念sama閱讀 212,816評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異矫限,居然都是意外死亡孽鸡,警方通過查閱死者的電腦和手機皮迟,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,729評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鱼的,“玉大人师郑,你說我怎么就攤上這事湿刽∪逝耄” “怎么了扶歪?”我有些...
    開封第一講書人閱讀 158,300評論 0 348
  • 文/不壞的土叔 我叫張陵霍弹,是天一觀的道長毫别。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么庐完? 我笑而不...
    開封第一講書人閱讀 56,780評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮域醇,結(jié)果婚禮上漆腌,老公的妹妹穿的比我還像新娘盟广。我一直安慰自己描融,他們只是感情好,可當我...
    茶點故事閱讀 65,890評論 6 385
  • 文/花漫 我一把揭開白布衡蚂。 她就那樣靜靜地躺著,像睡著了一般骏庸。 火紅的嫁衣襯著肌膚如雪毛甲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 50,084評論 1 291
  • 那天具被,我揣著相機與錄音玻募,去河邊找鬼。 笑死一姿,一個胖子當著我的面吹牛七咧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播叮叹,決...
    沈念sama閱讀 39,151評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼艾栋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了蛉顽?” 一聲冷哼從身側(cè)響起蝗砾,我...
    開封第一講書人閱讀 37,912評論 0 268
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎携冤,沒想到半個月后悼粮,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,355評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡曾棕,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,666評論 2 327
  • 正文 我和宋清朗相戀三年扣猫,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片翘地。...
    茶點故事閱讀 38,809評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡申尤,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出衙耕,到底是詐尸還是另有隱情瀑凝,我是刑警寧澤,帶...
    沈念sama閱讀 34,504評論 4 334
  • 正文 年R本政府宣布臭杰,位于F島的核電站粤咪,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏渴杆。R本人自食惡果不足惜寥枝,卻給世界環(huán)境...
    茶點故事閱讀 40,150評論 3 317
  • 文/蒙蒙 一宪塔、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧囊拜,春花似錦某筐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蜜托,卻和暖如春抄囚,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背橄务。 一陣腳步聲響...
    開封第一講書人閱讀 32,121評論 1 267
  • 我被黑心中介騙來泰國打工幔托, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蜂挪。 一個月前我還...
    沈念sama閱讀 46,628評論 2 362
  • 正文 我出身青樓重挑,卻偏偏與公主長得像,于是被迫代替她去往敵國和親棠涮。 傳聞我的和親對象是個殘疾皇子谬哀,可洞房花燭夜當晚...
    茶點故事閱讀 43,724評論 2 351

推薦閱讀更多精彩內(nèi)容