JavaScript第十五章節(jié) 使用Canvas繪圖(WebGL)

WebGL

WebGL 是針對 Canvas 的 3D 上下文桥胞。與其他 Web 技術(shù)不同,WebGL 并不是 W3C 制定的標(biāo)準(zhǔn),而
是由 Khronos Group 制定的。其官方網(wǎng)站是這樣介紹的:“Khronos Group 是一個(gè)非盈利的由會(huì)員資助的
協(xié)會(huì)昆码,專注于為并行計(jì)算以及各種平臺(tái)和設(shè)備上的圖形及動(dòng)態(tài)媒體制定無版稅的開放標(biāo)準(zhǔn)×诖ⅲ” Khronos
Group 也設(shè)計(jì)了其他圖形處理 API赋咽,比如 OpenGL ES 2.0。瀏覽器中使用的 WebGL 就是基于 OpenGL ES
2.0 制定的吨娜。

WebGL學(xué)習(xí)地址,
OpenGL

類型化數(shù)組

WebGL 涉及的復(fù)雜計(jì)算需要提前知道數(shù)值的精度脓匿,而標(biāo)準(zhǔn)的 JavaScript 數(shù)值無法滿足需要。為此宦赠,WebGL 引入了一個(gè)概念陪毡,叫類型化數(shù)組(typed arrays)米母。類型化數(shù)組也是數(shù)組,只不過其元素被設(shè)置為特定類型的值毡琉。
類型化數(shù)組的核心就是一個(gè)名為 ArrayBuffer 的類型爱咬。每個(gè) ArrayBuffer 對象表示的只是內(nèi)存中指定的字節(jié)數(shù),但不會(huì)指定這些字節(jié)用于保存什么類型的數(shù)據(jù)绊起。通過 ArrayBuffer 所能做的,就是為了將來使用而分配一定數(shù)量的字節(jié)燎斩。

視圖

使用 ArrayBuffer(數(shù)組緩沖器類型)的一種特別的方式就是用它來創(chuàng)建數(shù)組緩沖器視圖虱歪。其中,最常見的視圖是 DataView栅表,通過它可以選擇 ArrayBuffer中一小段字節(jié)笋鄙。為此,可以在創(chuàng)建 DataView實(shí)例的時(shí)候傳入一個(gè) ArrayBuffer怪瓶、一個(gè)可選的字節(jié)偏移量(從該字節(jié)開始選擇)和一個(gè)可選的要選
擇的字節(jié)數(shù)萧落。

示例:

//基于整個(gè)緩沖器創(chuàng)建一個(gè)新視圖
var view = new DataView(buffer);
//創(chuàng)建一個(gè)開始于字節(jié) 9 的新視圖
var view = new DataView(buffer, 9);
//創(chuàng)建一個(gè)從字節(jié) 9 開始到字節(jié) 18 的新視圖
var view = new DataView(buffer, 9, 10); 
類型化視圖

類型化視圖一般也被稱為類型化數(shù)組,因?yàn)樗鼈兂嗽乇仨毷悄撤N特定的數(shù)據(jù)類型外洗贰,與常規(guī)的
數(shù)組無異找岖。類型化視圖也分幾種,而且它們都繼承了 DataView敛滋。

  • Int8Array:表示 8 位二補(bǔ)整數(shù)许布。
  • Uint8Array:表示 8 位無符號(hào)整數(shù)。
  • Int16Array:表示 16 位二補(bǔ)整數(shù)绎晃。
  • Uint16Array:表示 16 位無符號(hào)整數(shù)蜜唾。
  • Int32Array:表示 32 位二補(bǔ)整數(shù)。
  • Uint32Array:表示 32 位無符號(hào)整數(shù)庶艾。
  • Float32Array:表示 32 位 IEEE 浮點(diǎn)值袁余。
  • Float64Array:表示 64 位 IEEE 浮點(diǎn)值。

WebGL上下文

目前咱揍,在支持的瀏覽器中颖榜,WebGL 的名字叫"experimental-webgl",這是因?yàn)?WebGL 規(guī)范仍然未制定完成述召。制定完成后朱转,這個(gè)上下文的名字就會(huì)變成簡單的"webgl"。如果瀏覽器不支持 WebGL积暖,那么取得該上下文時(shí)會(huì)返回 null藤为。

示例:

var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
 var gl = drawing.getContext("experimental-webgl");
 if (gl){
 //使用 WebGL
 }
} 

通過給 getContext()傳遞第二個(gè)參數(shù),可以為 WebGL 上下文設(shè)置一些選項(xiàng)夺刑。

  • alpha:值為 true缅疟,表示為上下文創(chuàng)建一個(gè) Alpha 通道緩沖區(qū)分别;默認(rèn)值為 true。
  • depth:值為 true存淫,表示可以使用 16 位深緩沖區(qū)耘斩;默認(rèn)值為 true。
  • stencil:值為 true桅咆,表示可以使用 8 位模板緩沖區(qū)括授;默認(rèn)值為 false。
  • antialias:值為 true岩饼,表示將使用默認(rèn)機(jī)制執(zhí)行抗鋸齒操作荚虚;默認(rèn)值為 true。
  • premultipliedAlpha:值為 true籍茧,表示繪圖緩沖區(qū)有預(yù)乘 Alpha 值版述;默認(rèn)值為 true。
  • preserveDrawingBuffer:值為 true寞冯,表示在繪圖完成后保留繪圖緩沖區(qū)渴析;默認(rèn)值為 false。

示例:

var drawing = document.getElementById("drawing");
//確定瀏覽器支持<canvas>元素
if (drawing.getContext){
 try {
 gl = drawing.getContext("experimental-webgl");
 } catch (ex) {
 //什么也不做
 }
 if (gl){
 //使用 WebGL
 } else {
 alert("WebGL context could not be created.");
 }
} 

常量

如果你熟悉 OpenGL吮龄,那肯定會(huì)對各種操作中使用非常多的常量印象深刻俭茧。這些常量在 OpenGL 中
都帶前綴 GL_。 在 WebGL 中漓帚,保存在上下文對象中的這些常量都沒有 GL_前綴恢恼。比如說,
GL_COLOR_BUFFER_BIT 常量在 WebGL 上下文中就是 gl.COLOR_BUFFER_BIT胰默。WebGL 以這種方式支
持大多數(shù) OpenGL 常量(有一部分常量是不支持的)场斑。

方法命名

OpenGL(以及 WebGL)中的很多方法都試圖通過名字傳達(dá)有關(guān)數(shù)據(jù)類型的信息。如果某方法可以
接收不同類型及不同數(shù)量的參數(shù)牵署,看方法名的后綴就可以知道漏隐。方法名的后綴會(huì)包含參數(shù)個(gè)數(shù)(1 到 4)
和接收的數(shù)據(jù)類型(f 表示浮點(diǎn)數(shù),i 表示整數(shù))奴迅。例如青责,gl.uniform4f()意味著要接收 4 個(gè)浮點(diǎn)數(shù),

而 gl.uniform3i()則表示要接收 3 個(gè)整數(shù)取具。
也有很多方法接收數(shù)組參數(shù)而非一個(gè)個(gè)單獨(dú)的參數(shù)脖隶。這樣的方法其名字中會(huì)包含字母 v(即 vector,
矢量)暇检。因此产阱,gl.uniform3iv()可以接收一個(gè)包含 3 個(gè)值的整數(shù)數(shù)組。請

準(zhǔn)備繪圖

在實(shí)際操作 WebGL 上下文之前块仆,一般都要使用某種實(shí)色清除<canvas>构蹬,為繪圖做好準(zhǔn)備王暗。為此,
首先必須使用 clearColor()方法來指定要使用的顏色值庄敛,該方法接收 4 個(gè)參數(shù):紅俗壹、綠、藍(lán)和透明度藻烤。
每個(gè)參數(shù)必須是一個(gè) 0 到 1 之間的數(shù)值绷雏,表示每種分量在最終顏色中的強(qiáng)度。

gl.clearColor(0,0,0,1); //black
gl.clear(gl.COLOR_BUFFER_BIT);

以上代碼把清理顏色緩沖區(qū)的值設(shè)置為黑色怖亭,然后調(diào)用了 clear()方法之众,這個(gè)方法與 OpenGL 中的
glClear()等價(jià)。傳入的參數(shù) gl.COLOR_BUFFER_BIT 告訴 WebGL 使用之前定義的顏色來填充相應(yīng)區(qū)
域依许。一般來說,都要先清理緩沖區(qū)缀蹄,然后再執(zhí)行其他繪圖操作峭跳。

視口與坐標(biāo)

開始繪圖之前,通常要先定義 WebGL 的視口(viewport)缺前。默認(rèn)情況下蛀醉,視口可以使用整個(gè)<canvas>
區(qū)域。要改變視口大小衅码,可以調(diào)用 viewport()方法并傳入 4 個(gè)參數(shù):(視口相對于<canvas>元素的)
x 坐標(biāo)拯刁、y 坐標(biāo)、寬度和高度逝段。

緩沖區(qū)

頂點(diǎn)信息保存在 JavaScript 的類型化數(shù)組中垛玻,使用之前必須轉(zhuǎn)換到 WebGL 的緩沖區(qū)。要?jiǎng)?chuàng)建緩沖區(qū)奶躯,可以調(diào)用 gl.createBuffer()帚桩,然后使用 gl.bindBuffer()綁定到 WebGL 上下文。這兩步做完之
后嘹黔,就可以用數(shù)據(jù)來填充緩沖區(qū)了账嚎。

調(diào)用 gl.bindBuffer()可以將 buffer 設(shè)置為上下文的當(dāng)前緩沖區(qū)。此后儡蔓,所有緩沖區(qū)操作都
直接在 buffer 中執(zhí)行郭蕉。因此,調(diào)用 gl.bufferData()時(shí)不需要明確傳入 buffer 也沒有問題喂江。最后
一行代碼使用 Float32Array 中的數(shù)據(jù)初始化了 buffer(一般都是用 Float32Array 來保存頂點(diǎn)信
息)召锈。如果想使用 drawElements()輸出緩沖區(qū)的內(nèi)容,也可以傳入 gl.ELEMENT_ARRAY_BUFFER获询。
gl.bufferData()的最后一個(gè)參數(shù)用于指定使用緩沖區(qū)的方式烟勋,取值范圍是如下幾個(gè)常量规求。

  • gl.STATIC_DRAW:數(shù)據(jù)只加載一次,在多次繪圖中使用卵惦。
  • gl.STREAM_DRAW:數(shù)據(jù)只加載一次阻肿,在幾次繪圖中使用。
  • gl.DYNAMIC_DRAW:數(shù)據(jù)動(dòng)態(tài)改變沮尿,在多次繪圖中使用丛塌。
  • gl.deleteBuffer(buffer):刪除緩存,釋放內(nèi)存

錯(cuò)誤

JavaScript 與 WebGL 之間的一個(gè)最大的區(qū)別在于畜疾,WebGL 操作一般不會(huì)拋出錯(cuò)誤赴邻。為了知道是否
有錯(cuò)誤發(fā)生,必須在調(diào)用某個(gè)可能出錯(cuò)的方法后啡捶,手工調(diào)用 gl.getError()方法姥敛。這個(gè)方法返回一個(gè)
表示錯(cuò)誤類型的常量∠故睿可能的錯(cuò)誤常量如下彤敛。

  • gl.NO_ERROR:上一次操作沒有發(fā)生錯(cuò)誤(值為 0)。
  • gl.INVALID_ENUM:應(yīng)該給方法傳入 WebGL 常量了赌,但卻傳錯(cuò)了參數(shù)墨榄。
  • gl.INVALID_VALUE:在需要無符號(hào)數(shù)的地方傳入了負(fù)值。
  • gl.INVALID_OPERATION:在當(dāng)前狀態(tài)下不能完成操作勿她。
  • gl.OUT_OF_MEMORY:沒有足夠的內(nèi)存完成操作袄秩。
  • gl.CONTEXT_LOST_WEBGL:由于外部事件(如設(shè)備斷電)干擾丟失了當(dāng)前 WebGL 上下文。

著色器

著色器(shader)是 OpenGL 中的另一個(gè)概念逢并。WebGL 中有兩種著色器:頂點(diǎn)著色器和片段(或像
素)著色器之剧。頂點(diǎn)著色器用于將 3D 頂點(diǎn)轉(zhuǎn)換為需要渲染的 2D 點(diǎn)。片段著色器用于準(zhǔn)確計(jì)算要繪制的每個(gè)像素的顏色砍聊。WebGL 著色器的獨(dú)特之處也是其難點(diǎn)在于猪狈,它們并不是用 JavaScript 寫的。這些著色
器是使用 GLSL(OpenGL Shading Language辩恼,OpenGL 著色語言)寫的雇庙,GLSL 是一種與 C 和 JavaScript
完全不同的語言。

編寫著色器

GLSL 是一種類 C 語言灶伊,專門用于編寫 OpenGL 著色器疆前。因?yàn)?WebGL 是 OpenGL ES 2.0 的實(shí)現(xiàn),所
以 OpenGL 中使用的著色器可以直接在 WebGL 中使用聘萨。這樣就方便了將桌面圖形應(yīng)用移植到瀏覽器中竹椒。
每個(gè)著色器都有一個(gè) main()方法,該方法在繪圖期間會(huì)重復(fù)執(zhí)行米辐。為著色器傳遞數(shù)據(jù)的方式有兩
種:Attribute 和 Uniform胸完。通過 Attribute 可以向頂點(diǎn)著色器中傳入頂點(diǎn)信息书释,通過 Uniform 可以向任何
著色器傳入常量值。Attribute 和 Uniform 在 main()方法外部定義赊窥,分別使用關(guān)鍵字 attribute 和
uniform爆惧。

編寫著色器程序

瀏覽器不能理解 GLSL 程序,因此必須準(zhǔn)備好字符串形式的 GLSL 程序锨能,以便編譯并鏈接到著色器
程序扯再。為便于使用,通常是把著色器包含在頁面的<script>標(biāo)簽內(nèi)址遇,并為該標(biāo)簽指定一個(gè)自定義的 type
屬性熄阻。由于無法識(shí)別 type 屬性值,瀏覽器不會(huì)解析<script>標(biāo)簽中的內(nèi)容倔约,但這不影響你讀寫其中
的代碼秃殉。

示例:

<script type="x-webgl/x-vertex-shader" id="vertexShader">
    attribute vec2 aVertexPosition;
    void main() {
     gl_Position = vec4(aVertexPosition, 0.0, 1.0);
    }
    </script>
    <script type="x-webgl/x-fragment-shader" id="fragmentShader">
    uniform vec4 uColor;
    void main() {
     gl_FragColor = uColor;
    }
</script> 
// 然后,可以通過 text 屬性提取出<script>元素的內(nèi)容:
var vertexGlsl = document.getElementById("vertexShader").text,
 fragmentGlsl = document.getElementById("fragmentShader").text;
 
// 創(chuàng)建著色器
// 要?jiǎng)?chuàng)建著色器對象浸剩,可以調(diào)用gl.createShader()方法并傳入要?jiǎng)?chuàng)建的著色器類型(gl.VERTEX_SHADER 或 gl.FRAGMENT_SHADER)钾军。編譯著色器使用的是 gl.compileShader()。

var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexGlsl);
gl.compileShader(vertexShader);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentGlsl);
gl.compileShader(fragmentShader); 

// 鏈接到著色器程序中乒省。

var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program); 

//通知webGL使用這個(gè)程序
gl.useProgram(program); 

為著色器傳入值

前面定義的著色器都必須接收一個(gè)值才能工作。為了給著色器傳入這個(gè)值畦木,必須先找到要接收這個(gè)
值的變量袖扛。對于 Uniform 變量,可以使用 gl.getUniformLocation()十籍,這個(gè)方法返回一個(gè)對象蛆封,表示
Uniform 變量在內(nèi)存中的位置。然后可以基于變量的位置來賦值勾栗。

示例:

var uColor = gl.getUniformLocation(program, "uColor");
gl.uniform4fv(uColor, [0, 0, 0, 1]); 
//第一行代碼從 program 中找到 Uniform 變量 uColor惨篱,返回了它在內(nèi)存中的位置。第二行代碼使用gl.uniform4fv()給 uColor 賦值围俘。

調(diào)試著色器和程序

WebGL 中的其他操作一樣砸讳,著色器操作也可能會(huì)失敗,而且也是靜默失敗界牡。如果你想知道著色
器或程序執(zhí)行中是否發(fā)生了錯(cuò)誤簿寂,必須親自詢問 WebGL 上下文。

if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)){
 alert(gl.getShaderInfoLog(vertexShader));
} 

繪圖

WebGL 只能繪制三種形狀:點(diǎn)宿亡、線和三角常遂。其他所有形狀都是由這三種基本形狀合成之后,再繪
制到三維空間中的挽荠。執(zhí)行繪圖操作要調(diào)用 gl.drawArrays()或 gl.drawElements()方法克胳,前者用于
數(shù)組緩沖區(qū)平绩,后者用于元素?cái)?shù)組緩沖區(qū)。

gl.drawArrays()或 gl.drawElements()的第一個(gè)參數(shù)都是一個(gè)常量漠另,表示要繪制的形狀捏雌。可
取值的常量范圍包括以下這些酗钞。

  • gl.POINTS:將每個(gè)頂點(diǎn)當(dāng)成一個(gè)點(diǎn)來繪制腹忽。
  • gl.LINES:將數(shù)組當(dāng)成一系列頂點(diǎn),在這些頂點(diǎn)間畫線砚作。每個(gè)頂點(diǎn)既是起點(diǎn)也是終點(diǎn)窘奏,因此數(shù)
    組中必須包含偶數(shù)個(gè)頂點(diǎn)才能完成繪制。
  • gl.LINE_LOOP:將數(shù)組當(dāng)成一系列頂點(diǎn)葫录,在這些頂點(diǎn)間畫線着裹。線條從第一個(gè)頂點(diǎn)到第二個(gè)頂點(diǎn),
    再從第二個(gè)頂點(diǎn)到第三個(gè)頂點(diǎn)米同,依此類推骇扇,直至最后一個(gè)頂點(diǎn)。然后再從最后一個(gè)頂點(diǎn)到第一
    個(gè)頂點(diǎn)畫一條線面粮。結(jié)果就是一個(gè)形狀的輪廓颜武。
  • gl.LINE_STRIP:除了不畫最后一個(gè)頂點(diǎn)與第一個(gè)頂點(diǎn)之間的線之外,其他與 gl.LINE_LOOP
    相同勉失。
  • gl.TRIANGLES:將數(shù)組當(dāng)成一系列頂點(diǎn)地技,在這些頂點(diǎn)間繪制三角形。除非明確指定柴底,每個(gè)三角
    形都單獨(dú)繪制婿脸,不與其他三角形共享頂點(diǎn)。
  • gl.TRIANGLES_STRIP:除了將前三個(gè)頂點(diǎn)之后的頂點(diǎn)當(dāng)作第三個(gè)頂點(diǎn)與前兩個(gè)頂點(diǎn)共同構(gòu)成
    一個(gè)新三角形外柄驻,其他都與 gl.TRIANGLES 相同狐树。例如,如果數(shù)組中包含 A鸿脓、B抑钟、C、D 四個(gè)頂
    點(diǎn)野哭,則第一個(gè)三角形連接 ABC味赃,而第二個(gè)三角形連接 BCD。
  • gl. TRIANGLES_FAN:除了將前三個(gè)頂點(diǎn)之后的頂點(diǎn)當(dāng)作第三個(gè)頂點(diǎn)與前一個(gè)頂點(diǎn)及第一個(gè)頂
    點(diǎn)共同構(gòu)成一個(gè)新三角形外虐拓,其他都與 gl.TRIANGLES 相同心俗。例如,如果數(shù)組中包含 A、B城榛、C揪利、
    D 四個(gè)頂點(diǎn),則第一個(gè)三角形連接 ABC狠持,而第二個(gè)三角形連接 ACD疟位。

紋理

WebGL 的紋理可以使用 DOM 中的圖像。要?jiǎng)?chuàng)建一個(gè)新紋理喘垂,可以調(diào)用 gl.createTexture()甜刻,
然后再將一幅圖像綁定到該紋理。如果圖像尚未加載到內(nèi)存中正勒,可能需要?jiǎng)?chuàng)建一個(gè) Image 對象的實(shí)例得院,
以便動(dòng)態(tài)加載圖像。圖像加載完成之前章贞,紋理不會(huì)初始化祥绞,因此,必須在 load 事件觸發(fā)后才能設(shè)置紋
理鸭限。

示例:

var image = new Image(),
 texture;
image.src = "smile.gif";
image.onload = function(){
 texture = gl.createTexture();
 gl.bindTexture(gl.TEXTURE_2D, texture);
 gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true);
 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, image);
 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
 gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
 //清除當(dāng)前紋理
 gl.bindTexture(gl.TEXTURE_2D, null);
} 

讀取像素

與 2D 上下文 類似蜕径,通過 WebGL 上下文也能讀取像素值。讀取像素值的方法 readPixels()與
OpenGL 中的同名方法只有一點(diǎn)不同败京,即最后一個(gè)參數(shù)必須是類型化數(shù)組兜喻。像素信息是從幀緩沖區(qū)讀取的,然后保存在類型化數(shù)組中赡麦。readPixels()方法的參數(shù)有:x朴皆、y、寬度隧甚、高度车荔、圖像格式渡冻、數(shù)據(jù)類
型和類型化數(shù)組戚扳。前 4 個(gè)參數(shù)指定讀取哪個(gè)區(qū)域中的像素。圖像格式參數(shù)幾乎總是 gl.RGBA族吻。數(shù)據(jù)類型
參數(shù)用于指定保存在類型化數(shù)組中的數(shù)據(jù)的類型帽借,但有以下限制。

  • 如果類型是 gl.UNSIGNED_BYTE超歌,則類型化數(shù)組必須是 Uint8Array砍艾。
  • 如果類型是 gl.UNSIGNED_SHORT_5_6_5、gl.UNSIGNED_SHORT_4_4_4_4 或 gl.UNSIGNED_
    SHORT_5_5_5_1巍举,則類型化數(shù)組必須是 Uint16Array脆荷。
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蜓谋,更是在濱河造成了極大的恐慌梦皮,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件桃焕,死亡現(xiàn)場離奇詭異剑肯,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)观堂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進(jìn)店門让网,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人师痕,你說我怎么就攤上這事溃睹。” “怎么了七兜?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵丸凭,是天一觀的道長。 經(jīng)常有香客問我腕铸,道長惜犀,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任狠裹,我火速辦了婚禮虽界,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘涛菠。我一直安慰自己莉御,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布俗冻。 她就那樣靜靜地躺著礁叔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪迄薄。 梳的紋絲不亂的頭發(fā)上琅关,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天,我揣著相機(jī)與錄音讥蔽,去河邊找鬼涣易。 笑死,一個(gè)胖子當(dāng)著我的面吹牛冶伞,可吹牛的內(nèi)容都是我干的新症。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼响禽,長吁一口氣:“原來是場噩夢啊……” “哼徒爹!你這毒婦竟也來了荚醒?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤隆嗅,失蹤者是張志新(化名)和其女友劉穎腌且,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體榛瓮,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡铺董,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了禀晓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片精续。...
    茶點(diǎn)故事閱讀 40,675評論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖粹懒,靈堂內(nèi)的尸體忽然破棺而出重付,到底是詐尸還是另有隱情,我是刑警寧澤凫乖,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布确垫,位于F島的核電站,受9級(jí)特大地震影響帽芽,放射性物質(zhì)發(fā)生泄漏删掀。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一导街、第九天 我趴在偏房一處隱蔽的房頂上張望披泪。 院中可真熱鬧,春花似錦搬瑰、人聲如沸款票。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽艾少。三九已至,卻和暖如春翼悴,著一層夾襖步出監(jiān)牢的瞬間缚够,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工抄瓦, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留潮瓶,地道東北人陶冷。 一個(gè)月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓钙姊,卻偏偏與公主長得像,于是被迫代替她去往敵國和親埂伦。 傳聞我的和親對象是個(gè)殘疾皇子煞额,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評論 2 360

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