OpenGL入門——?jiǎng)?chuàng)建窗口

1邑雅、初始化glfw

1.1 什么是glfw

glfw是一個(gè)輕量的可跨平臺(tái)的OpenGL庫函數(shù)嗦玖。主要是用來顯示窗口和捕捉窗口事件的一套API患雇。

1.2 創(chuàng)建一個(gè)窗口需要的原材料

  1. glad
  2. glfw
  3. glad.c文件
  4. 編譯器
  5. C/C++代碼

1.3 創(chuàng)建窗口的步驟

1.3.1 包含頭文件

// glad的頭文件需要在glfw的頭文件之上引入,引入后同時(shí)將glad.c文件復(fù)制到工程文件之下宇挫。
#include <glad/glad.h>
#include <GLFW/glfw3.h>
// 說明:如果出現(xiàn)glad頭文件無法提示苛吱,或者引入失敗,對(duì)于linux系統(tǒng)器瘪,
// 可以在/usr/local/include查看是否有g(shù)lad文件夾翠储,將glad文件夾的頭問價(jià)復(fù)制到這里即可
// 同時(shí)glad的頭文件還有一個(gè)KHR文件,也一并復(fù)制

1.3.2 初始化glfw

關(guān)于為什么要初始化glfw橡疼,我的理解是glfw是要作畫的工具援所,我們要做畫之前需要準(zhǔn)備一套完整的畫具,初始化glfw的過程就是準(zhǔn)備畫畫工具的一步欣除。

    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
    glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);

1.3.3 創(chuàng)建一個(gè)窗口對(duì)象并加入上下文

GLFWwindow * window ;
window = glfwCreateWindow(800,600,"hello world",NULL,NULL);
// 對(duì)使用glfw創(chuàng)建出來的window對(duì)象進(jìn)行非空校驗(yàn)
if (window == NULL)
 {
    std::cout<<"Faile create window."<< std::endl;
    glfwTerminate();
    return -1;
}
// 將創(chuàng)建的window對(duì)象加入到上下文中住拭,此時(shí)的window對(duì)象非空
glfwMakeContextCurrent(window);

加入上下文簡單來說就是加入到當(dāng)前運(yùn)行的進(jìn)程中,讓窗口對(duì)象為當(dāng)前顯示的對(duì)象历帚。

為什么會(huì)有上下文這個(gè)東西滔岳,可能會(huì)存在疑問,因?yàn)槲覀儾]有看到什么上下文啊挽牢。

解釋:

  1. OpenGL本身可以將它看做一個(gè)狀態(tài)機(jī)谱煤,引擎的不斷循環(huán),就是為了讓這個(gè)狀態(tài)機(jī)持續(xù)運(yùn)行下去禽拔,顯而易見的刘离,只有狀態(tài)機(jī)工作了才會(huì)顯示你想要的東西。

  2. 進(jìn)行過JAVA開發(fā)的或者了解開發(fā)的朋友應(yīng)該知道奏赘,JVM虛擬機(jī)寥闪,我們的JAVA代碼試運(yùn)行在JVM之上的太惠,那么類似的磨淌,OpenGL代碼是運(yùn)行在狀態(tài)機(jī)上的,至少我們可以抽象的理解為這樣凿渊。狀態(tài)機(jī)通過函數(shù)去操作GPU從而實(shí)現(xiàn)圖形的渲染梁只。

  3. 在java中我們是通過運(yùn)行main函數(shù),從而啟動(dòng)JVM運(yùn)行了JAVA代碼埃脏。那么類似的搪锣,再加入上下文之前,OpenGL創(chuàng)建的窗口彩掐,需要使用glfwMakeContextCurrent(window);這個(gè)函數(shù)啟動(dòng)狀態(tài)機(jī)构舟,或者可以理解為將我創(chuàng)建好的窗口顯示在狀態(tài)機(jī)上。

  4. 我們可以進(jìn)行一個(gè)小實(shí)驗(yàn)(實(shí)驗(yàn)結(jié)果就是我說的堵幽,不想觀看的可以跳過)

#include <glad/glad.h>
#include <GLFW/glfw3.h>

#include <iostream>

void pressToLine(GLFWwindow *window) {
    if(glfwGetKey(window,GLFW_KEY_P) == GLFW_PRESS)
    {
        glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
    }else if(glfwGetKey(window,GLFW_KEY_F)==GLFW_PRESS) 
    {
        glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
    }else if(glfwGetKey(window,GLFW_KEY_ESCAPE)==GLFW_PRESS) {
        glfwSetWindowShouldClose(window,true);
    }
}


int main()
{
    // 初始化glfw
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,4);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,6);
    glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
    // 創(chuàng)建窗口對(duì)象
    GLFWwindow *window;
    window = glfwCreateWindow(800,600,"triangle",NULL,NULL);
    





    // 判斷窗口對(duì)象創(chuàng)建是否成功
    if(window == NULL)
    {
        std::cout << "創(chuàng)建窗口失敼烦5臁!努咐!" << std::endl;
        glfwTerminate();
        return -1;
    }
    //將創(chuàng)建的窗口對(duì)象加載到上下文
    /**
     * @brief 這一步總是容易忘記
     */
    glfwMakeContextCurrent(window);

    // 使用glad加載glfw函數(shù)指針
    if (!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress))
    {
        std::cout << "Failed to initialize GLAD" << std::endl;
        return -1;
    }

    // 頂點(diǎn)數(shù)據(jù)
   float vertices[] = {
    -0.5f, -0.5f, 0.0f,
     0.5f, -0.5f, 0.0f,
     0.0f,  0.5f, 0.0f
};
    
    // 聲明頂點(diǎn)著色器和片段著色器
    unsigned int vertexShader,fragmentShader;
    // 創(chuàng)建頂點(diǎn)著色器
    vertexShader = glCreateShader(GL_VERTEX_SHADER);
    fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
    // 編譯著色器源碼
    const char* vertexShaderSource = "#version 330 core\n"
    "layout (location = 0) in vec3 aPos;\n"
    "void main()\n"
    "{\n"
    "   gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);\n"
    "}\0";
    const char *fragmentShaderSource = "#version 460 core\n"
    "out vec4 FragColor;\n"
    "void main()\n"
    "{\n"
    "   FragColor = vec4(1.0f, 0.5f, 0.2f, 1.0f);\n"
    "}\n\0";
    // 將glsl源碼編譯
    glShaderSource(vertexShader,1,&vertexShaderSource,NULL);
    glShaderSource(fragmentShader,1,&fragmentShaderSource,NULL);
    glCompileShader(vertexShader);
    glCompileShader(fragmentShader);
    // 校驗(yàn)編譯結(jié)果
    int success;
    // 定義一個(gè)錯(cuò)誤日志接收的變量
    char infoLog[512];
    glGetShaderiv(vertexShader, GL_COMPILE_STATUS, &success);
    // 對(duì)結(jié)果進(jìn)行校驗(yàn)
    if(!success) {
    // 校驗(yàn)失敗苦蒿,打印錯(cuò)誤信息
        glGetShaderInfoLog(vertexShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::VERTEX::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    glGetShaderiv(fragmentShader, GL_COMPILE_STATUS, &success);
    // 對(duì)結(jié)果進(jìn)行校驗(yàn)
    if(!success) {
    // 校驗(yàn)失敗,打印錯(cuò)誤信息
        glGetShaderInfoLog(fragmentShader, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n" << infoLog << std::endl;
    }
    // 創(chuàng)建著色器程序?qū)ο?    unsigned int shaderProgram;
    shaderProgram = glCreateProgram();
    // 將著色器添加進(jìn)去
    glAttachShader(shaderProgram,vertexShader);
    glAttachShader(shaderProgram,fragmentShader);
    // 鏈接OpenGL
    glLinkProgram(shaderProgram);
    // 鏈接結(jié)果校驗(yàn)
    glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
    if(!success) {
        glGetProgramInfoLog(shaderProgram, 512, NULL, infoLog);
        std::cout << "ERROR::SHADER::PROGRAM::LINKING_FAILED\n" << infoLog << std::endl;
    }

    // 創(chuàng)建VBO和VAO
    unsigned int VBO,VAO;
    // 生成VBO和VAO對(duì)象
    glGenBuffers(1,&VBO);
    glGenVertexArrays(1,&VAO);
    // 設(shè)置VAO和VBO
    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER,VBO);
    glBufferData(GL_ARRAY_BUFFER,sizeof(vertices),vertices,GL_STATIC_DRAW);
    // 設(shè)置頂點(diǎn)屬性
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3*sizeof(float),(void*)0);
    glEnableVertexAttribArray(0);


    // 編寫引擎
    while(!glfwWindowShouldClose(window))
    {
        // 設(shè)置清楚層顏色
        glClearColor(0.1f,0.2f,0.2f,1.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        // 使用創(chuàng)建的著色器程序
        glUseProgram(shaderProgram);
        glBindVertexArray(VAO); 
        glDrawArrays(GL_TRIANGLES,0,3);
        // 雙緩沖交換
        glfwSwapBuffers(window);
        // 檢測(cè)窗口事件
        glfwPollEvents();
        pressToLine(window);
    }

    glfwTerminate();
    return 0;
}

運(yùn)行上面的文件渗稍,不出錯(cuò)的情況下佩迟,你會(huì)得到一個(gè)三角形,如下圖所示


image.png

當(dāng)前使用的窗口對(duì)象為:

  // 創(chuàng)建窗口對(duì)象
    GLFWwindow *window;
    window = glfwCreateWindow(800,600,"triangle",NULL,NULL);

// 加入上下文的窗口對(duì)象也為該對(duì)象
glfwMakeContextCurrent(window);

現(xiàn)在我們創(chuàng)新創(chuàng)建一個(gè)window對(duì)象

// 創(chuàng)建測(cè)試窗口對(duì)象
    GLFWwindow *TestWindow;
    TestWindow = glfwCreateWindow(800,600,"triangle",NULL,NULL); 

// 將顯示三角形的窗口先加入上下文
glfwMakeContextCurrent(window);
glfwMakeContextCurrent(TestWindow);

我們得到結(jié)果:


image.png

得到了一個(gè)黑色的窗口竿屹,這個(gè)是我們的TestWindow报强,按照正常邏輯,此時(shí)其實(shí)不應(yīng)該一直顯示羔沙,應(yīng)該一閃而過躺涝。

這個(gè)原因是因?yàn)椋覀兝L制三角形的引擎一直在工作扼雏,所以會(huì)導(dǎo)致狀態(tài)機(jī)一直在運(yùn)行坚嗜,CPU沒有結(jié)束進(jìn)程。

這也說明了诗充,我們只是結(jié)束了狀態(tài)機(jī)對(duì)于三角形頁面的生命周期苍蔬,但是CPU沒有結(jié)束我們程序進(jìn)程的生命周期。

我們可以再將TestWidow先加入上下文蝴蜓,window后加入上下文碟绑,我們就會(huì)得到三角形窗口。

結(jié)論:加入上下文函數(shù)茎匠,是運(yùn)行OpenGL代碼的前提格仲,他會(huì)將描述好的OpenGL代碼加載入狀態(tài)機(jī)進(jìn)行顯示。

1.3.4 初始化glad/加載glfw的函數(shù)指針

glad的主要作用就是加載glfw的函數(shù)指針诵冒,glad和glew是具有相似功能的凯肋,都是進(jìn)行函數(shù)指針的加載,我們?nèi)绻皇褂胓lad汽馋,那么代碼將變得臃腫但又必要侮东,其中下面這為作者就將不使用glad函數(shù)庫的代碼展示了,可以看到代碼量是真的大1尽G难拧!
https://www.zhihu.com/question/344133077

image.png

有興趣可以看一下铁蹈。
言歸正傳宽闲,我們繼續(xù)創(chuàng)建窗口的操作,進(jìn)行初始化glad

if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
      std::cout << "glad init failed."<<std::endl;
      glfwTerminate();
      return -1;
}

這段代碼的核心含義就是當(dāng)加載glfw的函數(shù)指針失敗時(shí),將終止程序的運(yùn)行容诬,簡單來說就是加載glfw的函數(shù)指針來供程序的繼續(xù)運(yùn)行围辙。

1.3.5 創(chuàng)建窗口引擎

通過前面的步驟,我們可以實(shí)現(xiàn)窗口對(duì)象的創(chuàng)建放案,并且完成了將創(chuàng)建的窗口對(duì)象加載到了上下文中姚建,但是此時(shí)并沒有萬事大吉,創(chuàng)建的窗口對(duì)象如何一直顯示在屏幕上吱殉?這就用到了我們接下來要說的——引擎掸冤。
汽車發(fā)動(dòng)需要引擎,這世界上所有需要運(yùn)行起來的東西都需要一個(gè)引擎友雳。
創(chuàng)建窗口最簡單的引擎如下代碼所示:

while(!glfwWindowShouldClose(window))
{
    glfwSwapBuffers(window);
    glfwPollEvents();    
}

當(dāng)我們一直不進(jìn)行關(guān)閉的需求時(shí)稿湿,那么判斷結(jié)果一直為真,將持續(xù)進(jìn)行循環(huán)內(nèi)操作押赊,從而實(shí)現(xiàn)在屏幕中表現(xiàn)為持續(xù)進(jìn)行顯示饺藤。
glfwPollEvents(); 這個(gè)函數(shù)是檢測(cè)窗口發(fā)生了哪些事件的函數(shù),如果我們不使用這個(gè)函數(shù)流礁,窗口依然可以創(chuàng)建涕俗,但是你的窗口是無法正常關(guān)閉,處于不可控狀態(tài)神帅,所以這個(gè)函數(shù)是必要的再姑,glfwSwapBuffers(window);這個(gè)函數(shù)是雙緩沖的應(yīng)用。

雙緩沖

什么是雙緩沖找御,簡而言之就是兩個(gè)緩沖區(qū)元镀,一個(gè)緩沖區(qū)負(fù)責(zé)屏幕上顯示,另一個(gè)緩沖區(qū)負(fù)責(zé)下一幀屏幕顯示霎桅,從而達(dá)到實(shí)時(shí)進(jìn)行渲染的目的栖疑。在雙緩沖之前,使用的是單緩沖技術(shù)滔驶,那么單緩沖帶來的副作用就是讓屏幕在持續(xù)渲染時(shí)總是會(huì)閃爍一下遇革,這是由于第二幀畫面無法在對(duì)第一幀畫面結(jié)束后,立即完成渲染瓜浸。
雙緩沖的實(shí)現(xiàn)方式就是將澳淑,下一幀要渲染的窗口畫面存放在一個(gè)緩沖區(qū)中比原,另一個(gè)緩沖區(qū)存放當(dāng)前正在顯示的窗口畫面插佛。

1.3.6 程序的終止

其實(shí)完成上面的操作,便可以實(shí)現(xiàn)窗口的創(chuàng)建和關(guān)閉量窘,但是我們總是要養(yǎng)成一個(gè)好的習(xí)慣雇寇,在完成使用后,進(jìn)行手動(dòng)的關(guān)閉。

glfwTerminate();
return 0;

1.3.7 創(chuàng)建窗口的完整代碼如下:

#include <glad/glad.h>
#include <GLFW/glfw3.h>
#include <iostream>

int main() {
    glfwInit();
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR,3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR,3);
    glfwWindowHint(GLFW_OPENGL_PROFILE,GLFW_OPENGL_CORE_PROFILE);
    GLFWwindow * window ;
    window = glfwCreateWindow(800,600,"hello world",NULL,NULL);
    if (window == NULL)
    {
        std::cout<<"Faile create window."<< std::endl;
        glfwTerminate();
        return -1;
    }
    glfwMakeContextCurrent(window);

    // glad 加載glfw函數(shù)指針
    if(!gladLoadGLLoader((GLADloadproc)glfwGetProcAddress)) {
        std::cout << "glad init failed."<<std::endl;
        glfwTerminate();
        return -1;
    }
    while(!glfwWindowShouldClose(window))
    {
        // glClearColor(0.1f,0.2f,0.2f,1.0f);
        // glClear(GL_COLOR_BUFFER_BIT);
        glfwSwapBuffers(window);
        glfwPollEvents();    
    }
    glfwTerminate();
    return 0;
}

2锨侯、窗口渲染

2.1 對(duì)創(chuàng)建的窗口進(jìn)行顏色的渲染

glClearColor(0.1f,0.2f,0.2f,1.0f);
glClear(GL_COLOR_BUFFER_BIT);

只需要將上述兩句代碼加載雙緩沖運(yùn)行之前進(jìn)行即可嫩海,在執(zhí)行g(shù)lClear函數(shù)時(shí)會(huì)將在glClearColor中設(shè)置的顏色渲染到窗口上。
其中GL_COLOR_BUFFER_BIT這個(gè)為要進(jìn)行渲染的選項(xiàng)囚痴,目前只是想將窗口進(jìn)行渲染叁怪,因此我們只需要使用GL_COLOR_BUFFER_BIT這個(gè)即可,還有一個(gè)深度的選項(xiàng)和一個(gè)模型的選項(xiàng)深滚,分別為GL_DEPTH_BUFFER_BIT奕谭、GL_STENCIL_BUFFER_BIT。

2.2 通過鍵盤輸入完成關(guān)閉窗口

void overWindow(GLFWwindow *window){
    bool res = glfwGetKey(window,GLFW_KEY_ESCAPE) == GLFW_PRESS;
    if (res)
    {
        glfwSetWindowShouldClose(window,true);
    }
}

對(duì)于鍵盤輸入事件兩件事情是最重要的痴荐,

  1. 第一個(gè)就是glfwGetKey()函數(shù)血柳,他是獲取按鍵輸入的函數(shù),通過glfw按壓宏定義GLFW_PRESS來進(jìn)行判斷返回值與宏是否相等生兆,
  2. 從而完成對(duì)鍵盤是否按壓進(jìn)行判斷难捌,將判斷結(jié)果的bool值放在分支判斷中,
  3. 如果按壓之后鸦难,將glfwWindowShouldClose函數(shù)的返回值設(shè)置為true根吁,此時(shí)引擎的判斷就會(huì)為false,引擎停止工作合蔽,glfw執(zhí)行關(guān)閉窗口操作婴栽,程序正常退出。
  4. 這也是1.3.7中為什么需要在最后添加一個(gè)glfw的關(guān)閉函數(shù)的調(diào)用的原因辈末。

3愚争、視口

通常我們會(huì)將視口與窗口進(jìn)行混淆,窗口就是一個(gè)創(chuàng)建的窗口挤聘,視口是在窗口之上的轰枝,我們所有的繪制的圖形是在一個(gè)視口中進(jìn)行的,當(dāng)超過這個(gè)視口的大小之后组去,圖形會(huì)被隱藏鞍陨,不會(huì)繪制出來。
大多數(shù)我們的一個(gè)窗口只有一個(gè)視口从隆。
如果我們進(jìn)行縮放窗口時(shí)希望同時(shí)將視口進(jìn)行縮放诚撵,那么就設(shè)置一個(gè)回調(diào)函數(shù)即可。

void framebuffer_size_callback(GLFWwindow* window, int width, int height)
{
    glViewport(0, 0, width, height);
}

// 注冊(cè)回調(diào)函數(shù)到glfw
glfwSetFramebufferSizeCallback(window, framebuffer_size_callback);

至于注冊(cè)位置我們應(yīng)該放在glfw初始化完成之后键闺,也就是將glfw加入到上下文之后寿烟,在進(jìn)行回調(diào)函數(shù)的注冊(cè)。

4辛燥、創(chuàng)建窗口的流程圖

創(chuàng)建窗口.png
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末筛武,一起剝皮案震驚了整個(gè)濱河市缝其,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌徘六,老刑警劉巖内边,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異待锈,居然都是意外死亡漠其,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門竿音,熙熙樓的掌柜王于貴愁眉苦臉地迎上來辉懒,“玉大人,你說我怎么就攤上這事谍失】袅” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵快鱼,是天一觀的道長颠印。 經(jīng)常有香客問我,道長抹竹,這世上最難降的妖魔是什么线罕? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮窃判,結(jié)果婚禮上钞楼,老公的妹妹穿的比我還像新娘。我一直安慰自己袄琳,他們只是感情好询件,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著唆樊,像睡著了一般宛琅。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上逗旁,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天嘿辟,我揣著相機(jī)與錄音,去河邊找鬼片效。 笑死红伦,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的淀衣。 我是一名探鬼主播昙读,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼舌缤!你這毒婦竟也來了箕戳?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤国撵,失蹤者是張志新(化名)和其女友劉穎陵吸,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體介牙,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡壮虫,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了环础。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片囚似。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖线得,靈堂內(nèi)的尸體忽然破棺而出饶唤,到底是詐尸還是另有隱情,我是刑警寧澤贯钩,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布募狂,位于F島的核電站,受9級(jí)特大地震影響角雷,放射性物質(zhì)發(fā)生泄漏祸穷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一勺三、第九天 我趴在偏房一處隱蔽的房頂上張望雷滚。 院中可真熱鬧,春花似錦吗坚、人聲如沸祈远。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽绊含。三九已至,卻和暖如春炊汹,著一層夾襖步出監(jiān)牢的瞬間躬充,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工讨便, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留充甚,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓霸褒,卻偏偏與公主長得像伴找,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子废菱,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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