Unity的陰影

<meta charset="utf-8">

一.陰影的實現(xiàn)原理

image

1.1. Shadow Map

在 Unity 的實時渲染中肮疗,我們采用的是 Shadow Map 技術(shù)。
原理:計算光源的陰影映射紋理扒接,記錄光源的位置出發(fā)伪货、能看到的場景中距離它最近的表面位置。簡單理解就是先把攝像機的位置與光源重合钾怔,然后攝像機看不到的區(qū)域就是陰影碱呼。

前向渲染中,如果平行光開啟了陰影(要注意需要手動開啟宗侦,創(chuàng)建了一個新光源愚臀,默認是沒有陰影的),Unity 就會為這個平行光計算陰影映射紋理矾利。這張陰影映射紋理實質(zhì)就是一張深度紋理姑裂,記錄著從光源出發(fā),距離光源最近的表面信息男旗。

unity選擇使用一個額外的pass來專門更新光源的陰影映射紋理舶斧,即LightMode標簽被設(shè)為ShadowCaster的pass。這個pass的渲染目標不是幀緩存察皇,而是陰影映射紋理(或者深度紋理)

1.2.屏幕空間的陰影映射技術(shù)(ScreenShadowMap)

原理:此技術(shù)根據(jù)光源的陰影映射紋理和攝像機的深度紋理來得到屏幕空間的陰影圖茴厉。如果攝像機的深度圖記錄的表面深度大于陰影映射紋理中的深度值,說明表面是可見的什荣。
方式:1.先調(diào)用LightMode為ShaderCaster的pass得到可投射陰影的光源的陰影映射紋理以及相機的深度紋理
2.然后根據(jù)光源的陰影映射紋理和相機的深度紋理得到屏幕空間的陰影圖矾缓。

限制:陰影映射紋理本質(zhì)上是一張深度圖,這個技術(shù)原本是延遲渲染產(chǎn)生陰影的方法稻爬,所以顯卡需要支持MRT嗜闻。

1.3. 總結(jié)

1.如果想要一個物體接收其它的物體的陰影,就要在 shader 中對陰影映射紋理進行采樣因篇,把采樣結(jié)果和光照結(jié)果相乘得到陰影效果泞辐。
2.如果想要一個物體向其它物體投射陰影,就要把該物體加入到陰影映射紋理之中竞滓,這一步驟是在 Shadow Pass 中實現(xiàn)的咐吼。
3.如果想要一個光源產(chǎn)生陰影效果,則需要手動選擇陰影類型:No Shadows , Hard Shadows , Soft Shadows商佑。Hard Shadows 相對于 Soft Shadows 計算量少一些锯茄,能滿足大部分場景,邊緣不平滑,鋸齒明顯肌幽。

二.不透明物體的陰影

2.1. 讓物體投射陰影

unity中晚碾,讓一個物體投射或者接收陰影,通過Mesh Render組件中的Cast ShadowsReceive Shadow屬性來實現(xiàn)喂急。

image

當 shader 中沒有 ShadowCaster 的 Pass 時會去它的 Fallback 里面找格嘁,我們之前的 Fallback 為 Specular,Specular 中也沒有這個 Pass, 但Specular 的回調(diào)Fallback 調(diào)用了VertexLit廊移。想看源碼的讀者糕簿,可以在 Unity 官方下載 內(nèi)置著色器 ,解壓之后狡孔,在 builtin-shaders-xxx->DefaultResourcesExtra -> Normal-VertexLit .shader 找到以下代碼:

// Pass to render object as a shadow caster
      Pass 
      {
         Name "ShadowCaster"
         Tags { "LightMode" = "ShadowCaster" }

         CGPROGRAM
         #pragma vertex vert
         #pragma fragment frag
         #pragma target 2.0
         #pragma multi_compile_shadowcaster
         #pragma multi_compile_instancing // allow instanced shadow pass for most of the shaders
         #include "UnityCG.cginc"

         struct v2f {
             V2F_SHADOW_CASTER;
            UNITY_VERTEX_OUTPUT_STEREO
        };

         v2f vert( appdata_base v )
         {
             v2f o;
             UNITY_SETUP_INSTANCE_ID(v);
             UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);
             TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
             return o;
         }

        float4 frag( v2f i ) : SV_Target
        {
             SHADOW_CASTER_FRAGMENT(i)
        }
         ENDCG
    }

默認情況下懂诗,計算光源的陰影映射紋理會剔除掉物體的背面∶缦ィ可以將Cast Shadows設(shè)置為two sided來允許對物體的所有面都進行計算殃恒。.

2.2. 讓物體接收陰影

步驟:
1.在頂點著色器的輸出結(jié)構(gòu)體添加內(nèi)置宏SHADOW_COORDS,作用是聲明一個用于對陰影紋理采樣的坐標,參數(shù)是下一個可用的插值寄存器的索引值辱揭。

struct v2f {
    float4 pos : SV_POSITION;
    float3 worldNormal : TEXCOORD0;
    float3 worldPos : TEXCOORD1;
    SHADOW_COORDS(2)
};

2.在頂點著色器返回之前添加另一個內(nèi)置宏TRANSFER_SHADOW离唐,作用是在頂點著色器計算上一步聲明的陰影紋理坐標。

v2f vert(a2v v) {
    v2f o;
    ...
    // Pass shadow coordinates to pixel shader
    TRANSFER_SHADOW(o);         
    return o;
}

3.在片元著色器計算陰影值界阁,使用另一個內(nèi)置宏SHADOW_ATTENUATION侯繁。

fixed shadow = SHADOW_ATTENUATION(i);

4.將得到的陰影值與漫反射顏色胖喳,高光反射顏色相乘泡躯。

return fixed4(ambient + (diffuse + specular) * atten * shadow, 1.0);

注意點:這三個宏是天生的三個好基友,如果關(guān)閉了陰影丽焊,那么 SHADOW_COORDS较剃,TRANSFER_SHADOW 會不起作用,而 SHADOW_ATTENUATION 的值為 1 技健。那么漫反射顏色和高光反射顏色不受 shadow 影響写穴。而且這些宏會使用 v.vertex 和 a.pos 等變量來計算,所以 a2v 頂點坐標變量必須為 vertex雌贱,輸入結(jié)構(gòu)體 a2v 必須命名為 v 啊送,且 v2f 中頂點位置坐標為 pos。

2.3. 完善的的光照衰減和陰影管理

在Base Pass中欣孤,平行光的衰減因子總是等于1馋没,而在Additional Pass中,需要判斷該Pass處理的光源類型降传,再使用內(nèi)置變量和宏計算衰減因子篷朵。實際上,光照衰減和陰影對物體最終的渲染都是把光照衰減因子和陰影值以及光照結(jié)果相乘得到最終的渲染結(jié)果
Unity 提供了一個內(nèi)置宏UNITY_LIGHT_ATTENUATION來同時得到光照衰減因子和陰影值声旺。
UNITY_LIGHT_ATTENUATION在AutoLight中的定義:

#define UNITY_LIGHT_ATTENUATION(destName, input, worldPos) \
    unityShadowCoord3 lightCoord = mul(unity_WorldToLight,unityShadowCoord4(worldPos, 1)).xyz; \
    fixed shadow = UNITY_SHADOW_ATTENUATION(input, worldPos); \
    fixed destName = tex2D(_LightTexture0, dot(lightCoord, lightCoord).rr).r * shadow;
#endif

完整代碼:

Shader "Unity Shaders Book/Chapter 9/Attenuation And Shadow Use Build-in Functions" {
    Properties {
        _Diffuse ("Diffuse", Color) = (1, 1, 1, 1)
        _Specular ("Specular", Color) = (1, 1, 1, 1)
        _Gloss ("Gloss", Range(8.0, 256)) = 20
    }
    SubShader {
        Tags { "RenderType"="Opaque" }

        Pass {
            // Pass for ambient light & first pixel light (directional light)
            Tags { "LightMode"="ForwardBase" }

            CGPROGRAM

            // Apparently need to add this declaration
            #pragma multi_compile_fwdbase   

            #pragma vertex vert
            #pragma fragment frag

            // Need these files to get built-in macros
            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            fixed4 _Diffuse;
            fixed4 _Specular;
            float _Gloss;

            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
                SHADOW_COORDS(2)
            };

            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);

                o.worldNormal = UnityObjectToWorldNormal(v.normal);

                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

                // Pass shadow coordinates to pixel shader
                TRANSFER_SHADOW(o);

                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz;

                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));

                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
                fixed3 halfDir = normalize(worldLightDir + viewDir);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);

                // UNITY_LIGHT_ATTENUATION not only compute attenuation, but also shadow infos
                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

                return fixed4(ambient + (diffuse + specular) * atten, 1.0);
            }

            ENDCG
        }

        Pass {
            // Pass for other pixel lights
            Tags { "LightMode"="ForwardAdd" }

            Blend One One

            CGPROGRAM

            // Apparently need to add this declaration
            #pragma multi_compile_fwdadd
            // Use the line below to add shadows for point and spot lights
//          #pragma multi_compile_fwdadd_fullshadows

            #pragma vertex vert
            #pragma fragment frag

            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            fixed4 _Diffuse;
            fixed4 _Specular;
            float _Gloss;

            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
                SHADOW_COORDS(2)
            };

            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);

                o.worldNormal = UnityObjectToWorldNormal(v.normal);

                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

                // Pass shadow coordinates to pixel shader
                TRANSFER_SHADOW(o);

                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed3 diffuse = _LightColor0.rgb * _Diffuse.rgb * max(0, dot(worldNormal, worldLightDir));

                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(i.worldPos));
                fixed3 halfDir = normalize(worldLightDir + viewDir);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(worldNormal, halfDir)), _Gloss);

                // UNITY_LIGHT_ATTENUATION not only compute attenuation, but also shadow infos
                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

                return fixed4((diffuse + specular) * atten, 1.0);
            }

            ENDCG
        }
    }
    FallBack "Specular"
}

如果想在Additional Pass添加陰影效果笔链,需要將#pragma multi_compile_fwdadd編譯指令替換成#pragma multi_compile_fwdadd_fullshadows,使得這些額外的逐像素光源進行陰影計算腮猖。

三.透明物體的陰影

3.1透明度測試

透明度測試結(jié)合之前Unity shader學(xué)習(xí)---透明效果代碼鉴扫,把 Fallback 改為 VertexLit,
陰影部分相當于整個正方體的陰影澈缺,但鏤空區(qū)域不應(yīng)該有陰影幔妨。這是因為 VertexLit 中處理陰影的 Pass 并沒有做透明度測試的計算。所以為了提供這樣的一個 Pass 谍椅,我們可以更改 Fallback 為 "Transparent/Cutout/VertexLit" 误堡。要注意的是,需要提供一個 _CutOff 的屬性和 SHADOW_COORDS 的索引值〕裕現(xiàn)在看一下效果:

image

3.2透明度混合

Shader "Unity Shaders Book/Chapter 9/Alpha Blend With Shadow" {
    Properties {
        _Color ("Color Tint", Color) = (1, 1, 1, 1)
        _MainTex ("Main Tex", 2D) = "white" {}
        _AlphaScale ("Alpha Scale", Range(0, 1)) = 1
    }
    SubShader {
        Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}

        Pass {
            Tags { "LightMode"="ForwardBase" }

            ZWrite Off
            Blend SrcAlpha OneMinusSrcAlpha

            CGPROGRAM

            #pragma multi_compile_fwdbase

            #pragma vertex vert
            #pragma fragment frag

            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed _AlphaScale;

            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float3 worldNormal : TEXCOORD0;
                float3 worldPos : TEXCOORD1;
                float2 uv : TEXCOORD2;
                SHADOW_COORDS(3)
            };

            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);

                o.worldNormal = UnityObjectToWorldNormal(v.normal);

                o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;

                o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);

                // Pass shadow coordinates to pixel shader
                TRANSFER_SHADOW(o);

                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                fixed3 worldNormal = normalize(i.worldNormal);
                fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));

                fixed4 texColor = tex2D(_MainTex, i.uv);

                fixed3 albedo = texColor.rgb * _Color.rgb;

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

                fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));

                // UNITY_LIGHT_ATTENUATION not only compute attenuation, but also shadow infos
                UNITY_LIGHT_ATTENUATION(atten, i, i.worldPos);

                return fixed4(ambient + diffuse * atten, texColor.a * _AlphaScale);
            }

            ENDCG
        }
    } 
    FallBack "Transparent/VertexLit"
    // Or  force to apply shadow
//  FallBack "VertexLit"
}

image
image

四.完整的光照 shader

包含了法線紋理锁施,多光源,光照衰減和陰影杖们,基于 Blinn-Phong 的高光發(fā)射 shader悉抵。

Shader "Unity Shaders Book/Common/Bumped Specular" {
    Properties {
        _Color ("Color Tint", Color) = (1, 1, 1, 1)
        _MainTex ("Main Tex", 2D) = "white" {}
        _BumpMap ("Normal Map", 2D) = "bump" {}
        _Specular ("Specular Color", Color) = (1, 1, 1, 1)
        _Gloss ("Gloss", Range(8.0, 256)) = 20
    }
    SubShader {
        Tags { "RenderType"="Opaque" "Queue"="Geometry"}

        Pass { 
            Tags { "LightMode"="ForwardBase" }

            CGPROGRAM

            #pragma multi_compile_fwdbase   

            #pragma vertex vert
            #pragma fragment frag

            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _BumpMap;
            float4 _BumpMap_ST;
            fixed4 _Specular;
            float _Gloss;

            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float4 uv : TEXCOORD0;
                float4 TtoW0 : TEXCOORD1;  
                float4 TtoW1 : TEXCOORD2;  
                float4 TtoW2 : TEXCOORD3; 
                SHADOW_COORDS(4)
            };

            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);

                o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;

                TANGENT_SPACE_ROTATION;

                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  
                fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
                fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
                fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; 

                o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);  
                o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);  
                o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);  

                TRANSFER_SHADOW(o);

                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
                fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));

                fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
                bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));

                fixed3 albedo = tex2D(_MainTex, i.uv.xy).rgb * _Color.rgb;

                fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;

                fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(bump, lightDir));

                fixed3 halfDir = normalize(lightDir + viewDir);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss);

                UNITY_LIGHT_ATTENUATION(atten, i, worldPos);

                return fixed4(ambient + (diffuse + specular) * atten, 1.0);
            }

            ENDCG
        }

        Pass { 
            Tags { "LightMode"="ForwardAdd" }

            Blend One One

            CGPROGRAM

            #pragma multi_compile_fwdadd
            // Use the line below to add shadows for point and spot lights
//          #pragma multi_compile_fwdadd_fullshadows

            #pragma vertex vert
            #pragma fragment frag

            #include "Lighting.cginc"
            #include "AutoLight.cginc"

            fixed4 _Color;
            sampler2D _MainTex;
            float4 _MainTex_ST;
            sampler2D _BumpMap;
            float4 _BumpMap_ST;
            float _BumpScale;
            fixed4 _Specular;
            float _Gloss;

            struct a2v {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float4 tangent : TANGENT;
                float4 texcoord : TEXCOORD0;
            };

            struct v2f {
                float4 pos : SV_POSITION;
                float4 uv : TEXCOORD0;
                float4 TtoW0 : TEXCOORD1;  
                float4 TtoW1 : TEXCOORD2;  
                float4 TtoW2 : TEXCOORD3;
                SHADOW_COORDS(4)
            };

            v2f vert(a2v v) {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);

                o.uv.xy = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;
                o.uv.zw = v.texcoord.xy * _BumpMap_ST.xy + _BumpMap_ST.zw;

                float3 worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;  
                fixed3 worldNormal = UnityObjectToWorldNormal(v.normal);  
                fixed3 worldTangent = UnityObjectToWorldDir(v.tangent.xyz);  
                fixed3 worldBinormal = cross(worldNormal, worldTangent) * v.tangent.w; 

                o.TtoW0 = float4(worldTangent.x, worldBinormal.x, worldNormal.x, worldPos.x);
                o.TtoW1 = float4(worldTangent.y, worldBinormal.y, worldNormal.y, worldPos.y);
                o.TtoW2 = float4(worldTangent.z, worldBinormal.z, worldNormal.z, worldPos.z);  

                TRANSFER_SHADOW(o);

                return o;
            }

            fixed4 frag(v2f i) : SV_Target {
                float3 worldPos = float3(i.TtoW0.w, i.TtoW1.w, i.TtoW2.w);
                fixed3 lightDir = normalize(UnityWorldSpaceLightDir(worldPos));
                fixed3 viewDir = normalize(UnityWorldSpaceViewDir(worldPos));

                fixed3 bump = UnpackNormal(tex2D(_BumpMap, i.uv.zw));
                bump = normalize(half3(dot(i.TtoW0.xyz, bump), dot(i.TtoW1.xyz, bump), dot(i.TtoW2.xyz, bump)));

                fixed3 albedo = tex2D(_MainTex, i.uv.xy).rgb * _Color.rgb;

                fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(bump, lightDir));

                fixed3 halfDir = normalize(lightDir + viewDir);
                fixed3 specular = _LightColor0.rgb * _Specular.rgb * pow(max(0, dot(bump, halfDir)), _Gloss);

                UNITY_LIGHT_ATTENUATION(atten, i, worldPos);

                return fixed4((diffuse + specular) * atten, 1.0);
            }

            ENDCG
        }
    } 
    FallBack "Specular"
}

作者:無職轉(zhuǎn)生者
鏈接:http://www.reibang.com/p/79329716d74b
來源:簡書
著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán)摘完,非商業(yè)轉(zhuǎn)載請注明出處姥饰。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市孝治,隨后出現(xiàn)的幾起案子列粪,更是在濱河造成了極大的恐慌,老刑警劉巖谈飒,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件岂座,死亡現(xiàn)場離奇詭異,居然都是意外死亡杭措,警方通過查閱死者的電腦和手機费什,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來手素,“玉大人鸳址,你說我怎么就攤上這事∪常” “怎么了稿黍?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長祠斧。 經(jīng)常有香客問我闻察,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任辕漂,我火速辦了婚禮呢灶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘钉嘹。我一直安慰自己鸯乃,他們只是感情好,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布跋涣。 她就那樣靜靜地躺著缨睡,像睡著了一般。 火紅的嫁衣襯著肌膚如雪陈辱。 梳的紋絲不亂的頭發(fā)上奖年,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天,我揣著相機與錄音沛贪,去河邊找鬼陋守。 笑死,一個胖子當著我的面吹牛利赋,可吹牛的內(nèi)容都是我干的水评。 我是一名探鬼主播,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼媚送,長吁一口氣:“原來是場噩夢啊……” “哼中燥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起塘偎,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤疗涉,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后式塌,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡峰尝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了武学。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡火窒,死狀恐怖熏矿,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情票编,我是刑警寧澤,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布慧域,位于F島的核電站鲤竹,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏昔榴。R本人自食惡果不足惜辛藻,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望互订。 院中可真熱鬧吱肌,春花似錦、人聲如沸仰禽。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽坟瓢。三九已至勇边,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間折联,已是汗流浹背粒褒。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留诚镰,地道東北人奕坟。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像清笨,于是被迫代替她去往敵國和親月杉。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348