OpenGL ES:大長(zhǎng)腿效果

本案例的目的在于理解大長(zhǎng)腿效果的實(shí)現(xiàn)以及圖片的保存

大長(zhǎng)腿效果.gif

準(zhǔn)備工作

準(zhǔn)備工作主要有3部分

  • 主控制器UI界面邏輯:主要是一些控件的操作
  • 自定義的GLKView(LongLegView):用于顯示 & 更新紋理圖片
  • 兩個(gè)封裝的工具類
    • LongLegVertexAttribArrayBuffer:緩存區(qū)初始化&更新抄课、準(zhǔn)備繪制及繪制的封裝
    • LongLegHelper:著色器編譯及連接的封裝

大長(zhǎng)腿實(shí)現(xiàn) & 圖片保存

實(shí)現(xiàn)的功能模塊主要分為三部分

  • 第一次加載圖片
  • 拉伸圖片
  • 圖片保存

下圖為三部分的具體實(shí)現(xiàn)流程

實(shí)現(xiàn)效果流程圖.png

第一次加載圖片

第一次圖片的加載是使用GLKit加載袖迎,利用自定義的GLKView視圖,通過(guò)計(jì)算圖片的頂點(diǎn)數(shù)據(jù),繪制圖片并顯示到屏幕上尚蝌,整體的流程如圖所示

主要分為兩部分

  • 初始化視圖:為紋理的加載做準(zhǔn)備工作
  • 加載圖片:view上加載未拉伸的原圖
初始化視圖

這部分內(nèi)容主要是初始化頂點(diǎn)數(shù)組、上下文以及頂點(diǎn)數(shù)組緩存區(qū)旺韭,需要在加載圖片之前做好準(zhǔn)備

加載圖片

主要是使用GLKit加載原圖胶坠,有以下幾步

  • 設(shè)置上下滑桿按鈕
  • 設(shè)置zidingView的代理
  • 加載圖片
  • 設(shè)置初始化的拉伸區(qū)域

其中,加載圖片的流程如圖所示

在圖片繪制之前叔壤,還需要通過(guò)原圖的size以及設(shè)定的view的大小瞎饲,計(jì)算紋理的頂點(diǎn)數(shù)據(jù),其計(jì)算流程如下

這里需要介紹下以下計(jì)算

目前圖中數(shù)據(jù)是已經(jīng)拉伸后的數(shù)據(jù)炼绘,但在第一次加載時(shí)嗅战,newHeight、startY、endY都為0

  • 計(jì)算圖片的寬高比:根據(jù)已知的圖片大小和view的大小計(jì)算
  • 計(jì)算拉伸量 = (newHeight - (endY-startY)) * 紋理高度该窗,即換算成紋理的拉伸量
  • 計(jì)算紋理坐標(biāo):根據(jù)傳入的開始位置和結(jié)束位置的紋理坐標(biāo)計(jì)算
  • 計(jì)算頂點(diǎn)坐標(biāo):需要先將傳入的開始和結(jié)束的紋理坐標(biāo)換換算為頂點(diǎn)坐標(biāo)在計(jì)算頂點(diǎn)坐標(biāo)之前赫舒,需要計(jì)算出開始位置和結(jié)束位置的坐標(biāo)

然后根據(jù)開始坐標(biāo)和結(jié)束位置坐標(biāo)計(jì)算8個(gè)點(diǎn)的頂點(diǎn)

  • 繪制
    調(diào)用GLKView的display方法,系統(tǒng)會(huì)自動(dòng)回調(diào)GLKViewDelagate的代碼方法glkView: drawInRect,具體的繪制流程如下

拉伸圖片

大長(zhǎng)腿的拉伸厌漂,主要是通過(guò)兩部分控制的,首先需要通過(guò)上下滑塊選定需要拉伸的范圍斟珊,其次需要滑動(dòng)slider來(lái)決定拉伸范圍是拉長(zhǎng)還是縮短

滑塊調(diào)整

這部分就是通過(guò)兩個(gè)下上滑桿苇倡,確定拉伸范圍,主要流程如下

圖片拉伸過(guò)程

確定拉伸范圍后囤踩,需要通過(guò)操作slider來(lái)進(jìn)行圖片的拉伸旨椒,滑動(dòng)slider會(huì)改變slder的值,繼而回調(diào)slider的值改變方法堵漱,其實(shí)現(xiàn)流程吐下

在拉伸時(shí)综慎,需要根據(jù)拉伸區(qū)域以及slder的值重新計(jì)算紋理的頂點(diǎn)數(shù)據(jù),并重新繪制顯示到屏幕上勤庐,這部分的計(jì)算與前面提及的計(jì)算原理是一致的示惊,請(qǐng)參考前文計(jì)算原理

圖片保存

前兩兩部分將的都是紋理圖片的顯示,且都是通過(guò)GLKit框架顯示的愉镰,接下來(lái)我們需要說(shuō)明的是如何存儲(chǔ)拉伸后的紋理圖片米罚,這里就需要用到GLSL自定義的著色器來(lái)幫助我們完成圖片的存儲(chǔ),這里的保存實(shí)際是利用context重繪來(lái)實(shí)現(xiàn)的丈探,實(shí)現(xiàn)流程如下

由上圖可知录择,圖片的保存主要分為四部分

  • 獲取處理后的圖片
//從幀緩存區(qū)中獲取紋理圖片文件; 獲取當(dāng)前的渲染結(jié)果
- (UIImage *)createResult {
    
//    1、根據(jù)屏幕顯示的圖片,重新獲取頂點(diǎn) & 紋理坐標(biāo)
//    拉伸--顯示:baseEffect隘竭、圖片獲取--存儲(chǔ):GLSL
//    :頂點(diǎn)&紋理坐標(biāo)--GLSL繪制圖片--幀緩存區(qū)--紋理(即新的圖片)塘秦,當(dāng)次處理的結(jié)果作為下一次處理的初始圖片
    [self resetTextureWithOriginWidth:self.currentImageSize.width originHeight:self.currentImageSize.height topY:self.currentTextureStartY bottomY:self.currentTextureEndY newHeight:self.currentNewHeight];
    
//    2、綁定幀緩存區(qū)
    glBindBuffer(GL_FRAMEBUFFER, self.tmpFrameBuffer);
    
//    3动看、獲取新的圖片size
    CGSize imageSize = [self newImageSize];
    
//    4尊剔、從幀緩存區(qū)中獲取拉伸后的圖片
    UIImage *image = [self imageFromTextureWithWidth:imageSize.width height:imageSize.height];
    
//    5、將幀緩存區(qū)綁定0菱皆,清空
    glBindBuffer(GL_FRAMEBUFFER, 0);
    
//    6须误、返回拉伸后的圖片
    return image;
}
  • 根據(jù)屏幕上的顯示,重新計(jì)算頂點(diǎn)數(shù)據(jù)搔预,為重繪提供數(shù)據(jù)支持
    主要分為兩部分
    • 計(jì)算頂點(diǎn)數(shù)據(jù):這部分的計(jì)算邏輯與calculateOriginTextureCoordWithTextureSize函數(shù)中邏輯是一致的
    • 通過(guò)GLSL將頂點(diǎn)數(shù)據(jù)渲染成一張新的紋理圖片霹期,并存儲(chǔ)到幀緩存區(qū)

其實(shí)渲染到紋理的過(guò)程就是所謂的濾鏡鏈,即當(dāng)次處理的結(jié)果作為下一次處理的初始圖片:
1拯田、獲取頂點(diǎn)&紋理坐標(biāo)
2历造、通過(guò)GLSL利用1中的數(shù)據(jù)繪制圖片
3、將圖片存儲(chǔ)到幀緩存區(qū)
4船庇、從幀緩存區(qū)獲取的新圖片作為紋理吭产,即為下一次處理的初始圖片

/**
 根據(jù)當(dāng)前屏幕上的顯示,來(lái)重新創(chuàng)建紋理
 
 @param originWidth 紋理的原始實(shí)際寬度
 @param originHeight 紋理的原始實(shí)際高度
 @param topY 0 ~ 1鸭轮,拉伸區(qū)域的頂邊的縱坐標(biāo)
 @param bottomY 0 ~ 1臣淤,拉伸區(qū)域的底邊的縱坐標(biāo)
 @param newHeight 0 ~ 1,拉伸區(qū)域的新高度
 */
- (void)resetTextureWithOriginWidth:(CGFloat)originWidth
                       originHeight:(CGFloat)originHeight
                               topY:(CGFloat)topY
                            bottomY:(CGFloat)bottomY
                          newHeight:(CGFloat)newHeight {
   //1.新的紋理尺寸(新紋理圖片的寬高)
   GLsizei newTextureWidth = originWidth;
   GLsizei newTextureHeight = originHeight * (newHeight - (bottomY - topY)) + originHeight;
   
   //2.高度變化百分比
   CGFloat heightScale = newTextureHeight / originHeight;
   
   //3.在新的紋理坐標(biāo)下窃爷,重新計(jì)算topY邑蒋、bottomY
   CGFloat newTopY = topY / heightScale;
   CGFloat newBottomY = (topY + newHeight) / heightScale;
   
   //4.創(chuàng)建頂點(diǎn)數(shù)組與紋理數(shù)組(邏輯與calculateOriginTextureCoordWithTextureSize 中關(guān)于紋理坐標(biāo)以及頂點(diǎn)坐標(biāo)邏輯是一模一樣的)
   SenceVertex *tmpVertices = malloc(sizeof(SenceVertex) * kVerticesCount);
   tmpVertices[0] = (SenceVertex){{-1, 1, 0}, {0, 1}};
   tmpVertices[1] = (SenceVertex){{1, 1, 0}, {1, 1}};
   tmpVertices[2] = (SenceVertex){{-1, -2 * newTopY + 1, 0}, {0, 1 - topY}};
   tmpVertices[3] = (SenceVertex){{1, -2 * newTopY + 1, 0}, {1, 1 - topY}};
   tmpVertices[4] = (SenceVertex){{-1, -2 * newBottomY + 1, 0}, {0, 1 - bottomY}};
   tmpVertices[5] = (SenceVertex){{1, -2 * newBottomY + 1, 0}, {1, 1 - bottomY}};
   tmpVertices[6] = (SenceVertex){{-1, -1, 0}, {0, 0}};
   tmpVertices[7] = (SenceVertex){{1, -1, 0}, {1, 0}};
   
   
   ///下面開始渲染到紋理的流程(將結(jié)果渲染成一張新的紋理圖片)
   
   //1. 生成幀緩存區(qū);
   GLuint frameBuffer;
   GLuint texture;
   //glGenFramebuffers 生成幀緩存區(qū)對(duì)象名稱;
   glGenFramebuffers(1, &frameBuffer);
   //glBindFramebuffer 綁定一個(gè)幀緩存區(qū)對(duì)象;
   glBindFramebuffer(GL_FRAMEBUFFER, frameBuffer);
   
   //2. 生成紋理ID,綁定紋理;
   //glGenTextures 生成紋理ID
   glGenTextures(1, &texture);
   //glBindTexture 將一個(gè)紋理綁定到紋理目標(biāo)上;
   glBindTexture(GL_TEXTURE_2D, texture);
   //glTexImage2D 指定一個(gè)二維紋理圖像;
   glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, newTextureWidth, newTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
   
   //3. 設(shè)置紋理相關(guān)參數(shù)
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
   
   //4. 將紋理圖像加載到幀緩存區(qū)對(duì)象上;
//    幀緩存區(qū) 可以附著 渲染緩存區(qū),還可以加載紋理對(duì)象
   /*
    glFramebufferTexture2D (GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
    target: 指定幀緩沖目標(biāo),符合常量必須是GL_FRAMEBUFFER;
    attachment: 指定附著紋理對(duì)象的附著點(diǎn)GL_COLOR_ATTACHMENT0
    textarget: 指定紋理目標(biāo), 符合常量:GL_TEXTURE_2D
    teture: 指定要附加圖像的紋理對(duì)象;
    level: 指定要附加的紋理圖像的mipmap級(jí)別按厘,該級(jí)別必須為0医吊。
    */
    glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
   
   //5. 設(shè)置視口尺寸
   glViewport(0, 0, newTextureWidth, newTextureHeight);
   
   //6. 獲取著色器程序
   GLuint program = [LongLegHelper programWithShaderName:@"spring"];
   glUseProgram(program);
   
   //7. 獲取傳遞數(shù)據(jù)的入口
   GLuint positionSlot = glGetAttribLocation(program, "Position");
   GLuint textureSlot = glGetUniformLocation(program, "Texture");
   GLuint textureCoordsSlot = glGetAttribLocation(program, "TextureCoords");
   
   //8. 傳值,即傳遞紋理ID
   glActiveTexture(GL_TEXTURE0);
   glBindTexture(GL_TEXTURE_2D, self.baseEffect.texture2d0.name);
   glUniform1i(textureSlot, 0);
   
   //9.初始化緩存區(qū)逮京,即創(chuàng)建VBO
   LongLegVertexAttribArrayBuffer *vbo = [[LongLegVertexAttribArrayBuffer alloc] initWithAttribStride:sizeof(SenceVertex) numberOfVertices:kVerticesCount data:tmpVertices usage:GL_STATIC_DRAW];
   
   //10.準(zhǔn)備繪制,將紋理/頂點(diǎn)坐標(biāo)傳遞進(jìn)去;
//    頂點(diǎn) & 紋理坐標(biāo) -- 準(zhǔn)備繪制
   [vbo prepareToDrawWithAttrib:positionSlot numberOfCoordinates:3 attribOffset:offsetof(SenceVertex, positionCoord) shouldEnable:YES];
   [vbo prepareToDrawWithAttrib:textureCoordsSlot numberOfCoordinates:2 attribOffset:offsetof(SenceVertex, textureCoord) shouldEnable:YES];
   
   //11. 繪制
   [vbo drawArrayWithMode:GL_TRIANGLE_STRIP startVertexIndex:0 numberOfVertices:kVerticesCount];
   
   //12.解綁緩存
   glBindFramebuffer(GL_FRAMEBUFFER, 0);
   //13.釋放頂點(diǎn)數(shù)組
   free(tmpVertices);
   
   //14.保存臨時(shí)的紋理對(duì)象/幀緩存區(qū)對(duì)象;
   self.tmpTexture = texture;
   self.tmpFrameBuffer = frameBuffer;
}
  • 從幀緩存區(qū)中獲取拉伸后的圖片
    圖片存儲(chǔ)的本質(zhì)其實(shí)是利用上下文將幀緩存區(qū)的圖片像素點(diǎn)進(jìn)行重繪卿堂,得到一張新的圖片
// 返回某個(gè)紋理對(duì)應(yīng)的 UIImage,調(diào)用前先綁定對(duì)應(yīng)的幀緩存
- (UIImage *)imageFromTextureWithWidth:(int)width height:(int)height {
    
//    1懒棉、綁定幀緩存區(qū)
    glBindFramebuffer(GL_FRAMEBUFFER, self.tmpFrameBuffer);
    
//    2草描、將幀緩存區(qū)內(nèi)的圖片紋理繪制到圖片上
    //計(jì)算圖片的字節(jié)數(shù)
    int size = width * height * 4;
    GLubyte *buffer = malloc(size);
    /*
    
    glReadPixels (GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
    @功能: 讀取像素(理解為將已經(jīng)繪制好的像素,從顯存中讀取到內(nèi)存中;)
    @參數(shù)解讀:
    參數(shù)x,y,width,height: xy坐標(biāo)以及讀取的寬高;
    參數(shù)format: 顏色格式; GL_RGBA;
    參數(shù)type: 讀取到的內(nèi)容保存到內(nèi)存所用的格式;GL_UNSIGNED_BYTE 會(huì)把數(shù)據(jù)保存為GLubyte類型;
    參數(shù)pixels: 指針,像素?cái)?shù)據(jù)讀取后, 將會(huì)保存到該指針指向的地址內(nèi)存中;
    
    注意: pixels指針,必須保證該地址有足夠的可以使用的空間, 以容納讀取的像素?cái)?shù)據(jù); 例如一副256 * 256的圖像,如果讀取RGBA 數(shù)據(jù), 且每個(gè)數(shù)據(jù)保存在GLUbyte. 總大小就是 256 * 256 * 4 = 262144字節(jié), 即256M;
    int size = width * height * 4;
    GLubyte *buffer = malloc(size);
    */
    glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
    
    //使用data和size 數(shù)組來(lái)訪問(wèn)buffer數(shù)據(jù);
    /*
     CGDataProviderRef CGDataProviderCreateWithData(void *info, const void *data, size_t size, CGDataProviderReleaseDataCallback releaseData);
     @功能: 新的數(shù)據(jù)類型, 方便訪問(wèn)二進(jìn)制數(shù)據(jù);
     @參數(shù):
     參數(shù)info: 指向任何類型數(shù)據(jù)的指針, 或者為Null;
     參數(shù)data: 數(shù)據(jù)存儲(chǔ)的地址,buffer
     參數(shù)size: buffer的數(shù)據(jù)大小;
     參數(shù)releaseData: 釋放的回調(diào),默認(rèn)為空;
     
     */
    CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, size, NULL);
    //每個(gè)組件的位數(shù);
    int bitsPerComponent = 8;
    //像素占用的比特?cái)?shù)4 * 8 = 32;
    int bitsPerPixel = 32;
    //每一行的字節(jié)數(shù)
    int bytesPerRow = 4 * width;
    //顏色空間格式;
    CGColorSpaceRef colorSpaceRef = CGColorSpaceCreateDeviceRGB();
    //位圖圖形的組件信息 - 默認(rèn)的
    CGBitmapInfo bitmapInfo = kCGBitmapByteOrderDefault;
    //顏色映射
    CGColorRenderingIntent renderingIntent = kCGRenderingIntentDefault;

    
//    3、將幀緩存區(qū)里的像素點(diǎn)繪制到一張圖片上:讀取的數(shù)據(jù) -- 圖片
    /*
    CGImageCreate(size_t width, size_t height,size_t bitsPerComponent, size_t bitsPerPixel, size_t bytesPerRow,CGColorSpaceRef space, CGBitmapInfo bitmapInfo, CGDataProviderRef provider,const CGFloat decode[], bool shouldInterpolate,CGColorRenderingIntent intent);
    @功能:根據(jù)你提供的數(shù)據(jù)創(chuàng)建一張位圖;
    注意:size_t 定義的是一個(gè)可移植的單位,在64位機(jī)器上為8字節(jié),在32位機(jī)器上是4字節(jié);
    參數(shù)width: 圖片的寬度像素;
    參數(shù)height: 圖片的高度像素;
    參數(shù)bitsPerComponent: 每個(gè)顏色組件所占用的位數(shù), 比如R占用8位;
    參數(shù)bitsPerPixel: 每個(gè)顏色的比特?cái)?shù), 如果是RGBA則是32位, 4 * 8 = 32位;
    參數(shù)bytesPerRow :每一行占用的字節(jié)數(shù);
    參數(shù)space:顏色空間模式,CGColorSpaceCreateDeviceRGB
    參數(shù)bitmapInfo:kCGBitmapByteOrderDefault 位圖像素布局;
    參數(shù)provider: 圖片數(shù)據(jù)源提供者, 在CGDataProviderCreateWithData ,將buffer 轉(zhuǎn)為 provider 對(duì)象;
    參數(shù)decode: 解碼渲染數(shù)組, 默認(rèn)NULL
    參數(shù)shouldInterpolate: 是否抗鋸齒;
    參數(shù)intent: 圖片相關(guān)參數(shù);kCGRenderingIntentDefault
    
    */
    CGImageRef imageRef = CGImageCreate(width, height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);
    
//    4策严、此時(shí)的 imageRef 是上下顛倒的穗慕,調(diào)用 CG 的方法重新繪制一遍,剛好翻轉(zhuǎn)過(guò)來(lái)
    //創(chuàng)建一個(gè)圖片context
    UIGraphicsBeginImageContext(CGSizeMake(width, height));
    CGContextRef context = UIGraphicsGetCurrentContext();
    //將圖片繪制上去
    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef);
    //從context中獲取圖片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    //結(jié)束圖片context處理
    UIGraphicsEndImageContext();
    
    //釋放buffer
    free(buffer);
    //返回圖片
    return image;
}
  • 存儲(chǔ)到相冊(cè)
    將獲取的拉伸后的圖片通過(guò)蘋果自帶的Photos框架享钞,將其存儲(chǔ)到系統(tǒng)相冊(cè)
// 保存圖片到相冊(cè)
- (void)saveImage:(UIImage *)image {
    //將圖片通過(guò)PHPhotoLibrary保存到系統(tǒng)相冊(cè)
    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
        [PHAssetChangeRequest creationRequestForAssetFromImage:image];
    } completionHandler:^(BOOL success, NSError * _Nullable error) {
        NSLog(@"success = %d, error = %@ 圖片已保存到相冊(cè)", success, error);
    }];
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末揍诽,一起剝皮案震驚了整個(gè)濱河市诀蓉,隨后出現(xiàn)的幾起案子栗竖,更是在濱河造成了極大的恐慌暑脆,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,386評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件狐肢,死亡現(xiàn)場(chǎng)離奇詭異添吗,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)份名,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,142評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門碟联,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人僵腺,你說(shuō)我怎么就攤上這事鲤孵。” “怎么了辰如?”我有些...
    開封第一講書人閱讀 164,704評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵普监,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我琉兜,道長(zhǎng)凯正,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,702評(píng)論 1 294
  • 正文 為了忘掉前任豌蟋,我火速辦了婚禮廊散,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘梧疲。我一直安慰自己允睹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,716評(píng)論 6 392
  • 文/花漫 我一把揭開白布幌氮。 她就那樣靜靜地躺著缭受,像睡著了一般。 火紅的嫁衣襯著肌膚如雪浩销。 梳的紋絲不亂的頭發(fā)上贯涎,一...
    開封第一講書人閱讀 51,573評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音慢洋,去河邊找鬼塘雳。 笑死,一個(gè)胖子當(dāng)著我的面吹牛普筹,可吹牛的內(nèi)容都是我干的败明。 我是一名探鬼主播,決...
    沈念sama閱讀 40,314評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼太防,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼妻顶!你這毒婦竟也來(lái)了酸员?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,230評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤讳嘱,失蹤者是張志新(化名)和其女友劉穎幔嗦,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體沥潭,經(jīng)...
    沈念sama閱讀 45,680評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡邀泉,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,873評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了钝鸽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片汇恤。...
    茶點(diǎn)故事閱讀 39,991評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖拔恰,靈堂內(nèi)的尸體忽然破棺而出因谎,到底是詐尸還是另有隱情,我是刑警寧澤颜懊,帶...
    沈念sama閱讀 35,706評(píng)論 5 346
  • 正文 年R本政府宣布财岔,位于F島的核電站,受9級(jí)特大地震影響饭冬,放射性物質(zhì)發(fā)生泄漏使鹅。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,329評(píng)論 3 330
  • 文/蒙蒙 一昌抠、第九天 我趴在偏房一處隱蔽的房頂上張望患朱。 院中可真熱鬧,春花似錦炊苫、人聲如沸裁厅。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,910評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)执虹。三九已至,卻和暖如春唠梨,著一層夾襖步出監(jiān)牢的瞬間袋励,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,038評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工当叭, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人磺芭。 一個(gè)月前我還...
    沈念sama閱讀 48,158評(píng)論 3 370
  • 正文 我出身青樓醉箕,卻偏偏與公主長(zhǎng)得像徙垫,于是被迫代替她去往敵國(guó)和親姻报。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,941評(píng)論 2 355