實(shí)現(xiàn)隧道

使用不同Mip貼圖的紋理過濾模式唱凯,對(duì)一個(gè)隧道進(jìn)行渲染。代碼如下:

#include "GLTools.h"
#include "GLShaderManager.h"
#include "GLMatrixStack.h"
#include "GLFrustum.h"
#include "GLGeometryTransform.h"


//在Mac 系統(tǒng)下,`#include<glut/glut.h>` 在Windows 和 Linux上伏蚊,我們使?freeglut的靜態(tài)庫版本并且需要添加?個(gè)宏
#ifdef __APPLE__
#include <glut/glut.h>
#else
#define FREEGLUT_STATIC
#include <GL/glut.h>
#endif


GLShaderManager shaderManager; //著色器管理器
GLMatrixStack modelViewMatrix; //模型視圖矩陣
GLMatrixStack projectionMatrix; //投影矩陣
GLFrustum viewFrustum; //視景體
GLGeometryTransform transformPipeline; //幾何圖形變換管道

//4個(gè)批次容器類
GLBatch floorBatch; //地面
GLBatch ceilingBatch; //天花板
GLBatch leftWallBatch; //左墻面
GLBatch rightWallBatch; //右墻面

//深度初始值
GLfloat viewZ = -65.0f;

//紋理標(biāo)識(shí)符號(hào)
#define TEXTURE_BRICK 0 //墻面
#define TEXTURE_FLOOR 1 //地板
#define TEXTURE_CEILING 2 //紋理天花板
#define TEXTURE_COUNT 3 //紋理個(gè)數(shù)

GLuint textures[TEXTURE_COUNT]; //紋理標(biāo)記數(shù)組

//文件tag名字?jǐn)?shù)組
const char * szTextureFiles[TEXTURE_COUNT] = { "brick.tga", "floor.tga", "ceiling.tga" };







//菜單欄選擇
void ProcessMenu(int value)
{
    GLint iLoop;
    for (iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
    {
        /*
         綁定紋理 glBindTexture
         參數(shù)1:GL_TEXTURE_2D
         參數(shù)2:需要綁定的紋理對(duì)象
         */
        glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
        
        /*
         配置紋理參數(shù) glTexParameteri
         參數(shù)1:紋理模式
         參數(shù)2:紋理參數(shù)
         參數(shù)3:特定紋理參數(shù)
         */
        switch (value)
        {
            case 0:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器)巡通,GL_NEAREST(最鄰近過濾)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
                break;
                
            case 1:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器),GL_LINEAR(線性過濾)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
                break;
                
            case 2:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器)鹃祖,GL_NEAREST_MIPMAP_NEAREST(選擇最鄰近的Mip層溪椎,并執(zhí)行最鄰近過濾)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_NEAREST);
                break;
                
            case 3:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器),GL_NEAREST_MIPMAP_LINEAR(在Mip層之間執(zhí)行線性插補(bǔ)恬口,并執(zhí)行最鄰近過濾)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR);
                break;
                
            case 4:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器)校读,GL_NEAREST_MIPMAP_LINEAR(選擇最鄰近Mip層,并執(zhí)行線性過濾)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
                break;
            
            case 5:
                //GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER(縮小過濾器)祖能,GL_LINEAR_MIPMAP_LINEAR(在Mip層之間執(zhí)行線性插補(bǔ)歉秫,并執(zhí)行線性過濾,又稱為三線性過濾)
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
                break;
                
            case 6:
                //設(shè)置各向異性過濾
                GLfloat fLargest;
                //獲取各向異性過濾的最大數(shù)量
                glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &fLargest);
                //設(shè)置紋理參數(shù)(各向異性采樣)
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, fLargest);
                break;
                
            case 7:
                //設(shè)置各向同性過濾养铸,數(shù)量為1.0表示(各向同性采樣)
                glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1.0f);
                break;
 
        }
    }
    
    //觸發(fā)重繪
    glutPostRedisplay();
}



//ChangeSize 函數(shù):?定義函數(shù).通過glutReshaperFunc(函數(shù)名)注冊(cè)為重塑函數(shù).當(dāng)屏幕??發(fā)?變化/或者第?次創(chuàng)建窗?時(shí),會(huì)調(diào)?該函數(shù)調(diào)整窗???/視???.
void ChangeSize(int w ,int h)
{
    //1.防止對(duì)0進(jìn)行除法操作
    if(h == 0)
        h = 1;
    
    //設(shè)置視口窗口尺寸
    glViewport(0, 0, w, h);
    
    GLfloat fAspect = (GLfloat)w/(GLfloat)h;
    
    //創(chuàng)建投影矩陣
    viewFrustum.SetPerspective(80.0f,fAspect,1.0,120.0);
    //加載到投影矩陣堆棧上
    projectionMatrix.LoadMatrix(viewFrustum.GetProjectionMatrix());
    
    //設(shè)置變換管道以使用兩個(gè)矩陣堆棧
    transformPipeline.SetMatrixStacks(modelViewMatrix, projectionMatrix);
    
}


//在這個(gè)函數(shù)里能夠在渲染環(huán)境中進(jìn)行任何需要的初始化雁芙,它這里的設(shè)置并初始化紋理對(duì)象
void SetupRC()
{
    //黑色的背景
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f );
    shaderManager.InitializeStockShaders();
    
    GLbyte * pBytes;
    GLint iWidth, iHeight, iComponents;
    GLenum eFormat;
    GLint iLoop;
    
    //生成紋理標(biāo)記
    /*
     分配紋理對(duì)象 glGenTextures
     參數(shù)1:紋理對(duì)象的數(shù)量
     參數(shù)2:紋理對(duì)象標(biāo)識(shí)數(shù)組
     */
    glGenTextures(TEXTURE_COUNT, textures);
    //循環(huán)設(shè)置紋理數(shù)組的紋理參數(shù)
    for (iLoop = 0; iLoop < TEXTURE_COUNT; iLoop++)
    {
        /*
         綁定紋理對(duì)象 glBindTexture
         參數(shù)1:紋理模式,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_3D
         參數(shù)2:需要綁定的紋理對(duì)象
         */
        glBindTexture(GL_TEXTURE_2D, textures[iLoop]);
        
        /*
         加載tga文件
         參數(shù)1:紋理文件名稱
         參數(shù)2:文件寬度變量地址
         參數(shù)3:文件高度變量地址
         參數(shù)4:文件組件變量地址
         參數(shù)5:文件格式變量地址
         返回值:pBytes钞螟,指向圖像數(shù)據(jù)的指針
         */
        pBytes = gltReadTGABits(szTextureFiles[iLoop], &iWidth, &iHeight, &iComponents, &eFormat);
        
        //加載紋理兔甘、設(shè)置過濾器和包裝模式
        //GL_TEXTURE_MAG_FILTER(放大過濾器,GL_NEAREST(最鄰近過濾)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        //GL_TEXTURE_MIN_FILTER(縮小過濾器),GL_NEAREST(最鄰近過濾)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        //GL_TEXTURE_WRAP_S(s軸環(huán)繞),GL_CLAMP_TO_EDGE(環(huán)繞模式強(qiáng)制對(duì)范圍之外的紋理坐標(biāo)沿著合法的紋理單元的最后一行或一列進(jìn)行采樣)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        //GL_TEXTURE_WRAP_T(t軸環(huán)繞),GL_CLAMP_TO_EDGE(環(huán)繞模式強(qiáng)制對(duì)范圍之外的紋理坐標(biāo)沿著合法的紋理單元的最后一行或一列進(jìn)行采樣)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        
        /**載入紋理 glTexImage2D
         參數(shù)1:紋理維度鳞滨,GL_TEXTURE_2D
         參數(shù)2:mip貼圖層次
         參數(shù)3:紋理單元存儲(chǔ)的顏色成分(從讀取像素圖中獲得)
         參數(shù)4:加載紋理寬度
         參數(shù)5:加載紋理的高度
         參數(shù)6:加載紋理的深度
         參數(shù)7:像素?cái)?shù)據(jù)的數(shù)據(jù)類型,GL_UNSIGNED_BYTE無符號(hào)整型
         參數(shù)8:指向紋理圖像數(shù)據(jù)的指針
         */
        glTexImage2D(GL_TEXTURE_2D, 0, iComponents, iWidth, iHeight, 0, eFormat, GL_UNSIGNED_BYTE, pBytes);
        
        /**為紋理對(duì)象生成一組完整的mipmap glGenerateMipmap
        參數(shù)1:紋理維度裂明,GL_TEXTURE_1D,GL_TEXTURE_2D,GL_TEXTURE_2D
        */
        glGenerateMipmap(GL_TEXTURE_2D);
        
        //釋放原始紋理數(shù)據(jù),不再需要紋理原始數(shù)據(jù)了
        free(pBytes);
        
    }
    
    //設(shè)置幾何圖形頂點(diǎn)/紋理坐標(biāo)(上.下.左.右)
    GLfloat z;
    
    /*
     GLTools庫中的容器類太援,GBatch闽晦,
     void GLBatch::Begin(GLenum primitive,GLuint nVerts,GLuint nTextureUnits = 0);
     參數(shù)1:圖元枚舉值
     參數(shù)2:頂點(diǎn)數(shù)
     參數(shù)3:1組或者2組紋理坐標(biāo)
     */
    floorBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
    for (z = 60.0f; z >= 0.0f; z -= 10.0f)
    {
        floorBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
        floorBatch.Vertex3f(-10.0f, -10.0f, z);
        
        floorBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
        floorBatch.Vertex3f(10.0f, -10.0f, z);
        
        floorBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
        floorBatch.Vertex3f(-10.0f, -10.0f, z-10.0f);
        
        floorBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
        floorBatch.Vertex3f(10.0f, -10.0f, z-10.0f);
    }
    floorBatch.End();
    
    ceilingBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
    for(z = 60.0f; z >= 0.0f; z -=10.0f)
    {
        ceilingBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
        ceilingBatch.Vertex3f(-10.0f, 10.0f, z - 10.0f);
        
        ceilingBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
        ceilingBatch.Vertex3f(10.0f, 10.0f, z - 10.0f);
        
        ceilingBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
        ceilingBatch.Vertex3f(-10.0f, 10.0f, z);
        
        ceilingBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
        ceilingBatch.Vertex3f(10.0f, 10.0f, z);
    }
    ceilingBatch.End();
    
    leftWallBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
    for (z = 60.0f; z >= 0.0f; z -= 10.0f)
    {
        leftWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
        leftWallBatch.Vertex3f(-10.0f, -10.0f, z);

        leftWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
        leftWallBatch.Vertex3f(-10.0f, 10.0f, z);

        leftWallBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
        leftWallBatch.Vertex3f(-10.0f, -10.0f, z-10.0f);

        leftWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
        leftWallBatch.Vertex3f(-10.0f, 10.0f, z-10.0f);
    }
    leftWallBatch.End();
    
    rightWallBatch.Begin(GL_TRIANGLE_STRIP, 28, 1);
    for (z = 60.0f; z >= 0.0f; z -= 10.0f)
    {
        rightWallBatch.MultiTexCoord2f(0, 0.0f, 0.0f);
        rightWallBatch.Vertex3f(10.0f, -10.0f, z);

        rightWallBatch.MultiTexCoord2f(0, 0.0f, 1.0f);
        rightWallBatch.Vertex3f(10.0f, 10.0f, z);

        rightWallBatch.MultiTexCoord2f(0, 1.0f, 0.0f);
        rightWallBatch.Vertex3f(10.0f, -10.0f, z-10.0f);

        rightWallBatch.MultiTexCoord2f(0, 1.0f, 1.0f);
        rightWallBatch.Vertex3f(10.0f, 10.0f, z-10.0f);
    }
    rightWallBatch.End();
    
}

//刪除紋理對(duì)象
void ShutdownRC(void)
{
    glDeleteTextures(TEXTURE_COUNT, textures);
}

//上下左右鍵位控制移動(dòng)
void SpecialKeys(int key, int x, int y)
{
    
    if (key == GLUT_KEY_UP)
    {
        viewZ += 0.5f;
    }
    
    if (key == GLUT_KEY_DOWN)
    {
        viewZ -= 0.5f;
    }
    
    glutPostRedisplay();
}

//RenderScene 函數(shù):?定義函數(shù).通過glutDisplayFunc(函數(shù)名)注冊(cè)為顯示渲染函數(shù).當(dāng)屏幕發(fā)?變化/或者開發(fā)者主動(dòng)渲染會(huì)調(diào)?此函數(shù),?來實(shí)現(xiàn)數(shù)據(jù)->渲染過程
void RenderScene(void)
{
    
    //清理緩存區(qū)
    glClear(GL_COLOR_BUFFER_BIT);
    
    modelViewMatrix.PushMatrix();
    modelViewMatrix.Translate(0.0f, 0.0f, viewZ);
    
  
    //3.紋理替換矩陣著色器
    /*
     參數(shù)1:GLT_SHADER_TEXTURE_REPLACE(著色器標(biāo)簽)
     參數(shù)2:模型視圖投影矩陣
     參數(shù)3:紋理層
     */
    shaderManager.UseStockShader(GLT_SHADER_TEXTURE_REPLACE,transformPipeline.GetModelViewProjectionMatrix(),0);
    
    //4.綁定紋理
    /*
     參數(shù)1:紋理模式,GL_TEXTURE_1D提岔、GL_TEXTURE_2D仙蛉、GL_TEXTURE_3D
     參數(shù)2:需要綁定的紋理
     */
    glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_FLOOR]);
    floorBatch.Draw();
    
    glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_CEILING]);
    ceilingBatch.Draw();
    
    glBindTexture(GL_TEXTURE_2D, textures[TEXTURE_BRICK]);
    leftWallBatch.Draw();
    rightWallBatch.Draw();
  
    //模型視圖出棧
    modelViewMatrix.PopMatrix();
    
    //交換緩存區(qū)
    glutSwapBuffers();
    
    
}


//main 函數(shù): 程序??.OpenGL 是?向過程編程.所以你會(huì)發(fā)現(xiàn)利?OpenGL處理圖形/圖像都是鏈?zhǔn)叫问?以及基于OpenGL封裝的圖像處理框架也是鏈?zhǔn)骄幊?int main(int argc, char* argv[])
{
    gltSetWorkingDirectory(argv[0]);
    glutInit(&argc, argv);
    //申請(qǐng)一個(gè)顏色緩存區(qū)、雙緩存區(qū)
    glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA);
    //設(shè)置窗口的尺寸
    glutInitWindowSize(800, 800);
    //設(shè)置窗口的名稱
    glutCreateWindow("隧道");
    //注冊(cè)回調(diào)函數(shù)(改變尺寸)
    glutReshapeFunc(ChangeSize);
    //注冊(cè)顯示函數(shù)
    glutDisplayFunc(RenderScene);
    
    glutSpecialFunc(SpecialKeys);
    
    //添加菜單
    glutCreateMenu(ProcessMenu);
    glutAddMenuEntry("GL_NEAREST", 0);
    glutAddMenuEntry("GL_LINEAR", 1);
    glutAddMenuEntry("GL_NEAREST_MIPMAP_NEAREST", 2);
    glutAddMenuEntry("GL_NEAREST_MIPMAP_LINEAR", 3);
    glutAddMenuEntry("GL_LINEAR_MIPMAP_NEAREST", 4);
    glutAddMenuEntry("GL_LINEAR_MIPMAP_LINEAR", 5);
    glutAddMenuEntry("Anisotropic Filter", 6);
    glutAddMenuEntry("Anisotropic Off", 7);
    glutAttachMenu(GLUT_RIGHT_BUTTON);
    
    
    GLenum err = glewInit();
    if (GLEW_OK != err)
    {
        fprintf(stderr, "Error: %s\n", glewGetErrorString(err));
        return 1;
    }
    
    SetupRC();
   
    //runloop運(yùn)行循環(huán)
    glutMainLoop();
    
    ShutdownRC();
    
    return 0;
}

運(yùn)行效果如下:
隧道.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末碱蒙,一起剝皮案震驚了整個(gè)濱河市荠瘪,隨后出現(xiàn)的幾起案子夯巷,更是在濱河造成了極大的恐慌,老刑警劉巖哀墓,帶你破解...
    沈念sama閱讀 211,265評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件趁餐,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡篮绰,警方通過查閱死者的電腦和手機(jī)后雷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吠各,“玉大人臀突,你說我怎么就攤上這事〖致” “怎么了候学?”我有些...
    開封第一講書人閱讀 156,852評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長纵散。 經(jīng)常有香客問我梳码,道長,這世上最難降的妖魔是什么伍掀? 我笑而不...
    開封第一講書人閱讀 56,408評(píng)論 1 283
  • 正文 為了忘掉前任边翁,我火速辦了婚禮,結(jié)果婚禮上硕盹,老公的妹妹穿的比我還像新娘符匾。我一直安慰自己,他們只是感情好瘩例,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評(píng)論 5 384
  • 文/花漫 我一把揭開白布啊胶。 她就那樣靜靜地躺著,像睡著了一般垛贤。 火紅的嫁衣襯著肌膚如雪焰坪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,772評(píng)論 1 290
  • 那天聘惦,我揣著相機(jī)與錄音某饰,去河邊找鬼。 笑死善绎,一個(gè)胖子當(dāng)著我的面吹牛黔漂,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播禀酱,決...
    沈念sama閱讀 38,921評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼炬守,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了剂跟?” 一聲冷哼從身側(cè)響起减途,我...
    開封第一講書人閱讀 37,688評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤酣藻,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后鳍置,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體辽剧,經(jīng)...
    沈念sama閱讀 44,130評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評(píng)論 2 325
  • 正文 我和宋清朗相戀三年税产,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了怕轿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,617評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡砖第,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出环凿,到底是詐尸還是另有隱情梧兼,我是刑警寧澤,帶...
    沈念sama閱讀 34,276評(píng)論 4 329
  • 正文 年R本政府宣布智听,位于F島的核電站羽杰,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏到推。R本人自食惡果不足惜考赛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評(píng)論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望莉测。 院中可真熱鬧颜骤,春花似錦、人聲如沸捣卤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽董朝。三九已至鸠项,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間子姜,已是汗流浹背祟绊。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評(píng)論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留哥捕,地道東北人牧抽。 一個(gè)月前我還...
    沈念sama閱讀 46,315評(píng)論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像遥赚,于是被迫代替她去往敵國和親阎姥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評(píng)論 2 348