Metal -- 如何處理大批量頂點(diǎn)數(shù)據(jù)以及加載圖片

一柿赊、首先我們要知道如何劃分批量數(shù)據(jù)范圍以及如何處理小批量的頂點(diǎn)數(shù)據(jù)
  • 蘋果的官方文檔中對(duì)數(shù)據(jù)有如下說(shuō)明闷游,當(dāng)數(shù)據(jù)量小于4KB的時(shí)候瞻鹏,我們可以稱為小批量數(shù)據(jù)朦佩,當(dāng)頂點(diǎn)的數(shù)據(jù)量大于4KB時(shí)尖滚,數(shù)據(jù)量就很大了喉刘,我們可以叫大批量數(shù)據(jù)。主要區(qū)別在于蘋果對(duì)這兩種的數(shù)據(jù)量的處理方式不同漆弄。
  • 當(dāng)我們的頂點(diǎn)數(shù)據(jù)小于4KB時(shí)候睦裳,我們可以直接將頂點(diǎn)數(shù)據(jù)放在數(shù)組中,并使用- (void)setVertexBytes:(const void *)bytes length:(NSUInteger)length atIndex:(NSUInteger)index方法將數(shù)據(jù)傳遞到頂點(diǎn)著色器函數(shù)置逻。
  • 當(dāng)頂點(diǎn)數(shù)據(jù)量大于4KB時(shí)候推沸,我們可以使用一個(gè)叫MTLBuffer的對(duì)象,它能夠?qū)?shù)據(jù)存儲(chǔ)到頂點(diǎn)緩存區(qū)中,便于GPU對(duì)這些數(shù)據(jù)進(jìn)行快速的訪問(wèn)處理鬓催。
二肺素、如何使用Metal渲染一張圖片githubDemo地址
  • 思路:
    1.Render類設(shè)置頂點(diǎn)相關(guān)操作、設(shè)置渲染管道相關(guān)操作宇驾、加載紋理倍靡、- (void)drawInMTKView:(nonnull MTKView *)view代理方法進(jìn)行渲染;
    2.BaseShaderTypes.h文件來(lái)橋接OC和Metal方法课舍;
    3.BaseShaders.metal設(shè)置Metal的頂點(diǎn)著色器函數(shù)和片元著色器函數(shù)塌西;
    4.BaseImage類通過(guò)加載一個(gè)簡(jiǎn)單的TGA文件初始化這個(gè)圖像.只支持32bit的TGA文件;
  • BaseShaderTypes.h橋接文件的具體實(shí)現(xiàn),設(shè)置的結(jié)構(gòu)體以及枚舉即支持OC又支持Metal的調(diào)用筝尾,方法如下:

typedef enum BaseVertexInputIndex {
    
    //頂點(diǎn)
    BaseVertexInputIndexVertices   =0,
    
    //視圖大小
    BaseVertexInputIndexViewportSize=1,
    
}BaseVertexInputIndex;
//紋理索引
typedef enum BaseTextureIndex
{
    BaseTextureIndexBaseColor = 0
}BaseTextureIndex;

//結(jié)構(gòu)體
typedef struct {
    //像素空間位置
    vector_float2 position;
    
    //2D紋理
    vector_float2 textureCoordinate;
}BaseVertex;
  • Render類的實(shí)現(xiàn)邏輯

一捡需、設(shè)置頂點(diǎn)相關(guān)操作:
1.根據(jù)頂點(diǎn)/紋理坐標(biāo)建立一個(gè)MTLBuffer

static const BaseVertex quadVertices[] = {
        //像素坐標(biāo),紋理坐標(biāo)
        { {  250,  -250 },  { 1.f, 0.f } },
        { { -250,  -250 },  { 0.f, 0.f } },
        { { -250,   250 },  { 0.f, 1.f } },
        
        { {  250,  -250 },  { 1.f, 0.f } },
        { { -250,   250 },  { 0.f, 1.f } },
        { {  250,   250 },  { 1.f, 1.f } },
        
    };

2.創(chuàng)建我們的頂點(diǎn)緩沖區(qū)筹淫,并用我們的Qualsits數(shù)組初始化它站辉;

    _vertices = [_device newBufferWithBytes:quadVertices
                                     length:sizeof(quadVertices)
                                    options:MTLResourceStorageModeShared];

3.通過(guò)將字節(jié)長(zhǎng)度除以每個(gè)頂點(diǎn)的大小來(lái)計(jì)算頂點(diǎn)的數(shù)目;

    _numVertices = sizeof(quadVertices) / sizeof(BaseVertex);

二损姜、設(shè)置渲染管道相關(guān)操作:
1.創(chuàng)建我們的渲染通道;

//從項(xiàng)目中加載.metal文件,創(chuàng)建一個(gè)library
       id<MTLLibrary>defalutLibrary = [_device newDefaultLibrary];
       //從庫(kù)中加載頂點(diǎn)函數(shù)
       id<MTLFunction>vertexFunction = [defalutLibrary newFunctionWithName:@"vertexShader"];
       //從庫(kù)中加載片元函數(shù)
       id<MTLFunction> fragmentFunction = [defalutLibrary newFunctionWithName:@"fragmentShader"];

2.配置用于創(chuàng)建管道狀態(tài)的管道;

MTLRenderPipelineDescriptor *pipelineStateDescriptor = [[MTLRenderPipelineDescriptor alloc] init];
       //管道名稱
       pipelineStateDescriptor.label = @"Texturing Pipeline";
       //可編程函數(shù),用于處理渲染過(guò)程中的各個(gè)頂點(diǎn)
       pipelineStateDescriptor.vertexFunction = vertexFunction;
       //可編程函數(shù),用于處理渲染過(guò)程總的各個(gè)片段/片元
       pipelineStateDescriptor.fragmentFunction = fragmentFunction;
       //設(shè)置管道中存儲(chǔ)顏色數(shù)據(jù)的組件格式
       pipelineStateDescriptor.colorAttachments[0].pixelFormat = baseMTKView.colorPixelFormat;

3.同步創(chuàng)建并返回渲染管線對(duì)象;

 NSError *error = NULL;
    _pipeLineState = [_device newRenderPipelineStateWithDescriptor:pipelineStateDescriptor error:&error];
       //判斷是否創(chuàng)建成功
    if (!_pipeLineState)
       {
           NSLog(@"Failed to created pipeline state, error %@", error);
       }

4.使用_device創(chuàng)建commandQueue;

_commandQueue = [_device newCommandQueue];

三饰剥、加載紋理TGA文件
1.獲取tag的路徑

 NSURL *imageFileLocation = [[NSBundle mainBundle] URLForResource:@"Image"withExtension:@"tga"];
    //將tag文件->CCImage對(duì)象
    BaseImage *image = [[BaseImage alloc]initWithTGAFileAtLocation:imageFileLocation];
    //判斷圖片是否轉(zhuǎn)換成功
    if(!image)
    {
        NSLog(@"Failed to create the image from:%@",imageFileLocation.absoluteString);
        
    }

2.創(chuàng)建紋理描述對(duì)象

    MTLTextureDescriptor *textureDescriptor = [[MTLTextureDescriptor alloc]init];
    //表示每個(gè)像素有藍(lán)色,綠色,紅色和alpha通道.其中每個(gè)通道都是8位無(wú)符號(hào)歸一化的值.(即0映射成0,255映射成1);
    textureDescriptor.pixelFormat = MTLPixelFormatBGRA8Unorm;
    //設(shè)置紋理的像素尺寸
    textureDescriptor.width = image.width;
    textureDescriptor.height = image.height;
    //使用描述符從設(shè)備中創(chuàng)建紋理
    _texture = [_device newTextureWithDescriptor:textureDescriptor];
    //計(jì)算圖像每行的字節(jié)數(shù)
    NSUInteger bytesPerRow = 4 * image.width;

3.創(chuàng)建MTLRegion 結(jié)構(gòu)體

/*
     typedef struct
     {
     MTLOrigin origin; //開(kāi)始位置x,y,z
     MTLSize   size; //尺寸width,height,depth
     } MTLRegion;
     */
    //MLRegion結(jié)構(gòu)用于標(biāo)識(shí)紋理的特定區(qū)域。 demo使用圖像數(shù)據(jù)填充整個(gè)紋理摧阅;因此汰蓉,覆蓋整個(gè)紋理的像素區(qū)域等于紋理的尺寸。
    MTLRegion region = {
        {0,0,0},
        {image.width,image.height,1}
    };

4.復(fù)制圖片數(shù)據(jù)到texture

    [_texture replaceRegion:region mipmapLevel:0 withBytes:image.data.bytes bytesPerRow:bytesPerRow];

四棒卷、MTKViewDelegate代理方法實(shí)現(xiàn)
1.為當(dāng)前渲染的每個(gè)渲染傳遞創(chuàng)建一個(gè)新的命令緩沖區(qū);

 id<MTLCommandBuffer> commandBuffer = [_commandQueue commandBuffer];
    //指定緩存區(qū)名稱
    commandBuffer.label = @"MyCommand";

2.currentRenderPassDescriptor描述符包含currentDrawables的紋理顾孽、視圖的深度、模板和sample緩沖區(qū)和清晰的值娇跟。

 MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;

3.創(chuàng)建渲染命令編碼器,這樣我們才可以渲染到something;

 id<MTLRenderCommandEncoder> renderEncoder =
        [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
        //渲染器名稱
        renderEncoder.label = @"MyRenderEncoder";

4.設(shè)置我們繪制的可繪制區(qū)域;

 [renderEncoder setViewport:(MTLViewport){0.0, 0.0, _viewportSize.x, _viewportSize.y, -1.0, 1.0 }];

5.設(shè)置渲染管道;

        [renderEncoder setRenderPipelineState:_pipelineState];

6.加載數(shù)據(jù)(大批量數(shù)據(jù)存儲(chǔ)樣式);

//將數(shù)據(jù)加載到MTLBuffer --> 頂點(diǎn)函數(shù)
        [renderEncoder setVertexBuffer:_vertices
                                offset:0
                               atIndex:CCVertexInputIndexVertices];
        //將數(shù)據(jù)加載到MTLBuffer --> 頂點(diǎn)函數(shù)
        [renderEncoder setVertexBytes:&_viewportSize
                               length:sizeof(_viewportSize)
                              atIndex:CCVertexInputIndexViewportSize];

7.設(shè)置紋理對(duì)象;

[renderEncoder setFragmentTexture:_texture atIndex:CCTextureIndexBaseColor];

8.繪制;

        // @method drawPrimitives:vertexStart:vertexCount:
        //@brief 在不使用索引列表的情況下,繪制圖元
        //@param 繪制圖形組裝的基元類型
        //@param 從哪個(gè)位置數(shù)據(jù)開(kāi)始繪制,一般為0
        //@param 每個(gè)圖元的頂點(diǎn)個(gè)數(shù),繪制的圖型頂點(diǎn)數(shù)量
        /*
         MTLPrimitiveTypePoint = 0, 點(diǎn)
         MTLPrimitiveTypeLine = 1, 線段
         MTLPrimitiveTypeLineStrip = 2, 線環(huán)
         MTLPrimitiveTypeTriangle = 3,  三角形
         MTLPrimitiveTypeTriangleStrip = 4, 三角型扇
         */
        [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle
                          vertexStart:0
                          vertexCount:_numVertices];

9.表示已該編碼器生成的命令都已完成,并且從MTLCommandBuffer中分離;

        [renderEncoder endEncoding];

10.一旦框架緩沖區(qū)完成岩齿,使用當(dāng)前可繪制的進(jìn)度表;

        [commandBuffer presentDrawable:view.currentDrawable];

11.最后,在這里完成渲染并將命令緩沖區(qū)推送到GPU;

    [commandBuffer commit];
  • BaseShaders.metal類的實(shí)現(xiàn)
    1.設(shè)置結(jié)構(gòu)體
//結(jié)構(gòu)體
typedef struct
{
    
    float4 clipSpacePosition [[position]];
    float2 textureCoordinate;
    
} RasterizerData;

2.設(shè)置頂點(diǎn)著色函數(shù)

vertex RasterizerData
vertexShader(uint vertexID [[vertex_id]],
             constant BaseVertex *vertexArray [[buffer(BaseVertexInputIndexVertices)]],
             constant vector_float2 *viewportSizePointer [[buffer(BaseVertexInputIndexViewportSize)]])
{
    /*
     處理頂點(diǎn)數(shù)據(jù):
     1) 執(zhí)行坐標(biāo)系轉(zhuǎn)換,將生成的頂點(diǎn)剪輯空間寫入到返回值中.
     2) 將頂點(diǎn)顏色值傳遞給返回值
     */
    
    //定義out
    RasterizerData out;
    
    //初始化輸出剪輯空間位置
    out.clipSpacePosition = vector_float4(0.0, 0.0, 0.0, 1.0);
    
    // 索引到我們的數(shù)組位置以獲得當(dāng)前頂點(diǎn)
    // 我們的位置是在像素維度中指定的.
    float2 pixelSpacePosition = vertexArray[vertexID].position.xy;
    
    //將vierportSizePointer 從verctor_uint2 轉(zhuǎn)換為vector_float2 類型
    vector_float2 viewportSize = vector_float2(*viewportSizePointer);
    
    //每個(gè)頂點(diǎn)著色器的輸出位置在剪輯空間中(也稱為歸一化設(shè)備坐標(biāo)空間,NDC),剪輯空間中的(-1,-1)表示視口的左下角,而(1,1)表示視口的右上角.
    //計(jì)算和寫入 XY值到我們的剪輯空間的位置.為了從像素空間中的位置轉(zhuǎn)換到剪輯空間的位置,我們將像素坐標(biāo)除以視口的大小的一半.
    out.clipSpacePosition.xy = pixelSpacePosition / (viewportSize / 2.0);
    
    out.clipSpacePosition.z = 0.0f;
    out.clipSpacePosition.w = 1.0f;
    
    //把我們輸入的顏色直接賦值給輸出顏色. 這個(gè)值將于構(gòu)成三角形的頂點(diǎn)的其他顏色值插值,從而為我們片段著色器中的每個(gè)片段生成顏色值.
    out.textureCoordinate = vertexArray[vertexID].textureCoordinate;
    
    //完成! 將結(jié)構(gòu)體傳遞到管道中下一個(gè)階段:
    return out;
}

3.片元著色器函數(shù):當(dāng)頂點(diǎn)函數(shù)執(zhí)行3次,三角形的每個(gè)頂點(diǎn)執(zhí)行一次后,則執(zhí)行管道中的下一個(gè)階段.柵格化/光柵化.

// 片元函數(shù)
//[[stage_in]],片元著色函數(shù)使用的單個(gè)片元輸入數(shù)據(jù)是由頂點(diǎn)著色函數(shù)輸出.然后經(jīng)過(guò)光柵化生成的.單個(gè)片元輸入函數(shù)數(shù)據(jù)可以使用"[[stage_in]]"屬性修飾符.
//一個(gè)頂點(diǎn)著色函數(shù)可以讀取單個(gè)頂點(diǎn)的輸入數(shù)據(jù),這些輸入數(shù)據(jù)存儲(chǔ)于參數(shù)傳遞的緩存中,使用頂點(diǎn)和實(shí)例ID在這些緩存中尋址.讀取到單個(gè)頂點(diǎn)的數(shù)據(jù).另外,單個(gè)頂點(diǎn)輸入數(shù)據(jù)也可以通過(guò)使用"[[stage_in]]"屬性修飾符的產(chǎn)生傳遞給頂點(diǎn)著色函數(shù).
//被stage_in 修飾的結(jié)構(gòu)體的成員不能是如下這些.Packed vectors 緊密填充類型向量,matrices 矩陣,structs 結(jié)構(gòu)體,references or pointers to type 某類型的引用或指針. arrays,vectors,matrices 標(biāo)量,向量,矩陣數(shù)組.
fragment float4 fragmentShader(RasterizerData in [[stage_in]],
                               texture2d<half> colorTexture [[texture(BaseTextureIndexBaseColor)]])
{
    constexpr sampler textureSampler(mag_filter::linear,
                                     min_filter::linear);
    
    const half4 colorSampler = colorTexture.sample(textureSampler,in.textureCoordinate);
    
    return float4(colorSampler);
    
    //返回輸入的片元顏色
    //return in.color;
}

  • 三、小批量頂點(diǎn)數(shù)據(jù)存儲(chǔ)樣式BaseMetalDemo地址
    - (void)setVertexBytes:(const void *)bytes length:(NSUInteger)length atIndex:(NSUInteger)index使用該方法來(lái)處理低于4KB的數(shù)據(jù)量苞俘,
- (void)drawInMTKView:(nonnull MTKView *)view {
   
    //1.頂點(diǎn)數(shù)據(jù)/顏色數(shù)據(jù)
    static const BaseVertex triangleVertices[] =
    {
        //頂點(diǎn),    RGBA 顏色值
        { {  0.5, -0.25, 0.0, 1.0 }, { 1, 0, 0, 1 } },
        { { -0.5, -0.25, 0.0, 1.0 }, { 0, 1, 0, 1 } },
        { { -0.0f, 0.25, 0.0, 1.0 }, { 0, 0, 1, 1 } },
    };
    
    //2.當(dāng)前渲染的每一個(gè)渲染創(chuàng)建一個(gè)新的命令緩存區(qū)
    id<MTLCommandBuffer>commandBuffer = [_commandQueue commandBuffer];
    
    //指定緩存區(qū)名字
    commandBuffer.label = @"MyCommand";
    
    //3.MTLRenderPassDescriptor:一組渲染目標(biāo)盹沈,用作渲染通道生成的像素的輸出目標(biāo)。
    MTLRenderPassDescriptor *renderPassDescriptor = view.currentRenderPassDescriptor;
    //判斷渲染目標(biāo)是否為空
    if(renderPassDescriptor != nil){
        //4.創(chuàng)建渲染命令編碼器吃谣,這樣我們才能渲染事物
        id<MTLRenderCommandEncoder>renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:renderPassDescriptor];
        //渲染器名稱
        renderEncoder.label = @"MyRenderEncoder";
        
        //5.設(shè)置可繪制的區(qū)域
        /*
        typedef struct {
            double originX, originY, width, height, znear, zfar;
        } MTLViewport;
         */
        //視口指定Metal渲染內(nèi)容的drawable區(qū)域乞封。 視口是具有x和y偏移,寬度和高度以及近和遠(yuǎn)平面的3D區(qū)域
        //為管道分配自定義視口需要通過(guò)調(diào)用setViewport:方法將MTLViewport結(jié)構(gòu)編碼為渲染命令編碼器岗憋。 如果未指定視口肃晚,Metal會(huì)設(shè)置一個(gè)默認(rèn)視口,其大小與用于創(chuàng)建渲染命令編碼器的drawable相同仔戈。
        MTLViewport viewPort = {
            0.0,0.0,_viewportSize.x,_viewportSize.y,-1.0,1.0
        };
        [renderEncoder setViewport:viewPort];
        
        //6.設(shè)置當(dāng)前渲染管道對(duì)象
        [renderEncoder setRenderPipelineState:_pipelineState];
        
        
        //7.從應(yīng)用程序OC 代碼 中發(fā)送數(shù)據(jù)給Metal 頂點(diǎn)著色器 函數(shù)
        //頂點(diǎn)數(shù)據(jù)+顏色數(shù)據(jù)
        //   1) 指向要傳遞給著色器的內(nèi)存的指針
        //   2) 我們想要傳遞的數(shù)據(jù)的內(nèi)存大小
        //   3)一個(gè)整數(shù)索引关串,它對(duì)應(yīng)于我們的“vertexShader”函數(shù)中的緩沖區(qū)屬性限定符的索引拧廊。
        [renderEncoder setVertexBytes:&triangleVertices length:sizeof(triangleVertices) atIndex:BaseVertexInputIndexVertices];
        
        //viewPortSize 數(shù)據(jù)
        //1) 發(fā)送到頂點(diǎn)著色函數(shù)中,視圖大小
        //2) 視圖大小內(nèi)存空間大小
        //3) 對(duì)應(yīng)的索引
        [renderEncoder setVertexBytes:&_viewportSize
                               length:sizeof(_viewportSize)
                              atIndex:BaseVertexInputIndexViewportSize];
        //8.畫出三角形的3個(gè)頂點(diǎn)
        // @method drawPrimitives:vertexStart:vertexCount:
        //@brief 在不使用索引列表的情況下,繪制圖元
        //@param 繪制圖形組裝的基元類型
        //@param 從哪個(gè)位置數(shù)據(jù)開(kāi)始繪制,一般為0
        //@param 每個(gè)圖元的頂點(diǎn)個(gè)數(shù),繪制的圖型頂點(diǎn)數(shù)量
        /*
         MTLPrimitiveTypePoint = 0, 點(diǎn)
         MTLPrimitiveTypeLine = 1, 線段
         MTLPrimitiveTypeLineStrip = 2, 線環(huán)
         MTLPrimitiveTypeTriangle = 3,  三角形
         MTLPrimitiveTypeTriangleStrip = 4, 三角型扇
         */
        [renderEncoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:3];
        
        //9.表示已該編碼器生成的命令都已完成,并且從MTLCommandBuffer中分離
        [renderEncoder endEncoding];
        
        //10.一旦框架緩沖區(qū)完成,使用當(dāng)前可繪制的進(jìn)度表
        [commandBuffer presentDrawable:view.currentDrawable];

        
    }
    //11.最后,在這里完成渲染并將命令緩沖區(qū)推送到GPU
    [commandBuffer commit];
    
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末晋修,一起剝皮案震驚了整個(gè)濱河市吧碾,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌墓卦,老刑警劉巖倦春,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異落剪,居然都是意外死亡睁本,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門忠怖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)呢堰,“玉大人,你說(shuō)我怎么就攤上這事脑又∧弘剩” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵问麸,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我钞翔,道長(zhǎng)严卖,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任布轿,我火速辦了婚禮哮笆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘汰扭。我一直安慰自己稠肘,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布萝毛。 她就那樣靜靜地躺著项阴,像睡著了一般。 火紅的嫁衣襯著肌膚如雪笆包。 梳的紋絲不亂的頭發(fā)上环揽,一...
    開(kāi)封第一講書人閱讀 51,370評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音庵佣,去河邊找鬼歉胶。 笑死,一個(gè)胖子當(dāng)著我的面吹牛巴粪,可吹牛的內(nèi)容都是我干的通今。 我是一名探鬼主播粥谬,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼辫塌!你這毒婦竟也來(lái)了帝嗡?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤璃氢,失蹤者是張志新(化名)和其女友劉穎哟玷,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體一也,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡巢寡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了椰苟。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抑月。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖舆蝴,靈堂內(nèi)的尸體忽然破棺而出谦絮,到底是詐尸還是另有隱情,我是刑警寧澤洁仗,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布层皱,位于F島的核電站,受9級(jí)特大地震影響赠潦,放射性物質(zhì)發(fā)生泄漏叫胖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一她奥、第九天 我趴在偏房一處隱蔽的房頂上張望瓮增。 院中可真熱鬧,春花似錦哩俭、人聲如沸绷跑。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)砸捏。三九已至,卻和暖如春讳苦,著一層夾襖步出監(jiān)牢的瞬間带膜,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工鸳谜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留膝藕,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓咐扭,卻偏偏與公主長(zhǎng)得像芭挽,于是被迫代替她去往敵國(guó)和親滑废。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354