青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

  C++博客 :: 首頁 :: 聯系 ::  :: 管理
  163 Posts :: 4 Stories :: 350 Comments :: 0 Trackbacks

常用鏈接

留言簿(48)

我參與的團隊

搜索

  •  

積分與排名

  • 積分 - 402530
  • 排名 - 59

最新評論

閱讀排行榜

評論排行榜

歡迎來到另一個激動人心的課程,這課的代碼是Banu Cosmin所寫,當然教程還是我自己寫的。在這課里,我將教你創建真正的反射,基于物理的。
由于它將用到蒙板緩存,所以需要耗費一些資源。當然隨著顯卡和CPU的發展,這些都不是問題了,好了讓我們開始吧!
 
  
  
 下面我們設置光源的參數 
  

static GLfloat    LightAmb[] = {0.7f, 0.7f, 0.7f, 1.0f};                // 環境光
static GLfloat    LightDif[] = {1.0f, 1.0f, 1.0f, 1.0f};                // 漫射光
static GLfloat    LightPos[] = {4.0f, 4.0f, 6.0f, 1.0f};                // 燈光的位置
  
 下面用二次幾何體創建一個球,并設置紋理 
  

GLUquadricObj    *q;                                // 使用二次幾何體創建球

GLfloat        xrot        =  0.0f;                        // X方向的旋轉角度
GLfloat        yrot        =  0.0f;                        // Y方向的旋轉角的
GLfloat        xrotspeed    =  0.0f;                            // X方向的旋轉速度
GLfloat        yrotspeed    =  0.0f;                            // Y方向的旋轉速度
GLfloat        zoom        = -7.0f;                        // 移入屏幕7個單位
GLfloat        height        =  2.0f;                        // 球離開地板的高度

GLuint        texture[3];                            // 使用三個紋理
  
 ReSizeGLScene() 和LoadBMP() 沒有變化 
  

GLvoid ReSizeGLScene(GLsizei width, GLsizei height)

AUX_RGBImageRec *LoadBMP(char *Filename)

  
 下面的代碼載入紋理 
  

int LoadGLTextures()                                // 載入*.bmp文件,并轉化為紋理
{
    int Status=FALSE;                               
    AUX_RGBImageRec *TextureImage[3];                        // 創建三個圖象
    memset(TextureImage,0,sizeof(void *)*3);                   
    if ((TextureImage[0]=LoadBMP("Data/EnvWall.bmp")) &&                // 載入地板圖像
        (TextureImage[1]=LoadBMP("Data/Ball.bmp")) &&                    // 載入球圖像
        (TextureImage[2]=LoadBMP("Data/EnvRoll.bmp")))                    // 載入強的圖像
    {
        Status=TRUE;                           
        glGenTextures(3, &texture[0]);                    // 創建紋理
        for (int loop=0; loop<3; loop++)                    // 循環設置三個紋理參數
        {
            glBindTexture(GL_TEXTURE_2D, texture[loop]);
            glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[loop]->sizeX, TextureImage[loop]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[loop]->data);
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
            glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
        }
        for (loop=0; loop<3; loop++)                   
        {
            if (TextureImage[loop])                   
            {
                if (TextureImage[loop]->data)           
                {
                    free(TextureImage[loop]->data);       
                }
                free(TextureImage[loop]);           
            }
        }
    }
    return Status;                                // 成功返回
}

  
 一個新的函數glClearStencil被加入到初始化代碼中,它用來設置清空操作后蒙板緩存中的值。其他的操作保持不變。 
  

int InitGL(GLvoid)                                // 初始化OpenGL
{
    if (!LoadGLTextures())                        // 載入紋理
    {
        return FALSE;                           
    }
    glShadeModel(GL_SMOOTH);                       
    glClearColor(0.2f, 0.5f, 1.0f, 1.0f);                   
    glClearDepth(1.0f);                           
    glClearStencil(0);                            // 設置蒙板值
    glEnable(GL_DEPTH_TEST);                       
    glDepthFunc(GL_LEQUAL);                       
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);           
    glEnable(GL_TEXTURE_2D);                        // 使用2D紋理
  
 下面的代碼用來啟用光照 
  

    glLightfv(GL_LIGHT0, GL_AMBIENT, LightAmb);           
    glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDif);               
    glLightfv(GL_LIGHT0, GL_POSITION, LightPos);           
    glEnable(GL_LIGHT0);   
    glEnable(GL_LIGHTING);

  
 下面的代碼使用二次幾何體創建一個球體,在前面的教程中都已經詳纖,這里不再重復。 
  

    q = gluNewQuadric();                            // 創建一個二次幾何體
    gluQuadricNormals(q, GL_SMOOTH);                        // 使用平滑法線
    gluQuadricTexture(q, GL_TRUE);                        // 使用紋理

    glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);                // 設置球紋理映射
    glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);           

    return TRUE;                                // 初始化完成,成功返回
}

  
 下面的代碼繪制我們的球 
  

void DrawObject()                                // 繪制我們的球
{
    glColor3f(1.0f, 1.0f, 1.0f);                    // 設置為白色
    glBindTexture(GL_TEXTURE_2D, texture[1]);                // 設置為球的紋理
    gluSphere(q, 0.35f, 32, 16);                    // 繪制球
  
 繪制完一個白色的球后,我們使用環境貼圖來繪制另一個球,把這兩個球按alpha混合起來。 
  

    glBindTexture(GL_TEXTURE_2D, texture[2]);                // 設置為環境紋理
    glColor4f(1.0f, 1.0f, 1.0f, 0.4f);                    // 使用alpha為40%的白色
    glEnable(GL_BLEND);                        // 啟用混合
    glBlendFunc(GL_SRC_ALPHA, GL_ONE);                    // 把原顏色的40%與目標顏色混合
    glEnable(GL_TEXTURE_GEN_S);                        // 使用球映射
    glEnable(GL_TEXTURE_GEN_T);                       

    gluSphere(q, 0.35f, 32, 16);                    // 繪制球體,并混合

    glDisable(GL_TEXTURE_GEN_S);                    // 讓OpenGL回到默認的屬性
    glDisable(GL_TEXTURE_GEN_T);                       
    glDisable(GL_BLEND);                           
}

  
 繪制地板 
  

void DrawFloor()           
{
    glBindTexture(GL_TEXTURE_2D, texture[0]);                // 選擇地板紋理,地板由一個長方形組成
    glBegin(GL_QUADS);                           
        glNormal3f(0.0, 1.0, 0.0);                   
        glTexCoord2f(0.0f, 1.0f);                    // 左下
        glVertex3f(-2.0, 0.0, 2.0);                   

        glTexCoord2f(0.0f, 0.0f);                    // 左上
        glVertex3f(-2.0, 0.0,-2.0);                   

        glTexCoord2f(1.0f, 0.0f);                    // 右上
        glVertex3f( 2.0, 0.0,-2.0);                   

        glTexCoord2f(1.0f, 1.0f);                    // 右下
        glVertex3f( 2.0, 0.0, 2.0);               
    glEnd();                               
}

  
 現在到了我們繪制函數的地方,我們將把所有的模型結合起來創建一個反射的場景。
向往常一樣先把各個緩存清空,接著定義我們的剪切平面,它用來剪切我們的圖像。這個平面的方程為equ[]={0,-1,0,0},向你所看到的它的法線是指向-y軸的,這告訴我們你只能看到y軸坐標小于0的像素,如果你啟用剪切功能的話。
關于剪切平面,我們在后面會做更多的討論。繼續吧:) 
  

int DrawGLScene(GLvoid)
{
    // 清除緩存
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);

    // 設置剪切平面
    double eqr[] = {0.0f,-1.0f, 0.0f, 0.0f};               
  
 下面我們把地面向下平移0.6個單位,因為我們的眼睛在y=0的平面,如果不平移的話,那么看上去平面就會變為一條線,為了看起來更真實,我們平移了它。 
  

    glLoadIdentity();                           
    glTranslatef(0.0f, -0.6f, zoom);                    // 平移和縮放地面

  
 下面我們設置了顏色掩碼,在默認情況下所有的顏色都可以寫入,即在函數glColorMask中,所有的參數都被設為GL_TRUE,如果設為零表示這部分顏色不可寫入。現在我們不希望在屏幕上繪制任何東西,所以把參數設為0。 
  

    glColorMask(0,0,0,0);

  
 下面來設置蒙板緩存和蒙板測試。
首先我們啟用蒙板測試,這樣就可以修改蒙板緩存中的值。

下面我們來解釋蒙板測試函數的含義:
當你使用glEnable(GL_STENCIL_TEST)啟用蒙板測試之后,蒙板函數用于確定一個顏色片段是應該丟棄還是保留(被繪制)。蒙板緩存區中的值與參考值ref進行比較,比較標準是func所指定的比較函數。參考值和蒙板緩存區的值都可以與掩碼進行為AND操作。蒙板測試的結果還導致蒙板緩存區根據glStencilOp函數所指定的行為進行修改。
func的參數值如下:

常量 含義
GL_NEVER 從不通過蒙板測試
GL_ALWAYS 總是通過蒙板測試
GL_LESS 只有參考值<(蒙板緩存區的值&mask)時才通過
GL_LEQUAL 只有參考值<=(蒙板緩存區的值&mask)時才通過
GL_EQUAL 只有參考值=(蒙板緩存區的值&mask)時才通過
GL_GEQUAL 只有參考值>=(蒙板緩存區的值&mask)時才通過
GL_GREATER 只有參考值>(蒙板緩存區的值&mask)時才通過
GL_NOTEQUAL 只有參考值!=(蒙板緩存區的值&mask)時才通過

接下來我們解釋glStencilOp函數,它用來根據比較結果修改蒙板緩存區中的值,它的函數原形為:
void glStencilOp(GLenum sfail, GLenum zfail, GLenum zpass),各個參數的含義如下:
sfail
當蒙板測試失敗時所執行的操作

zfail
當蒙板測試通過,深度測試失敗時所執行的操作

zpass
當蒙板測試通過,深度測試通過時所執行的操作

具體的操作包括以下幾種
常量 描述
GL_KEEP 保持當前的蒙板緩存區值
GL_ZERO 把當前的蒙板緩存區值設為0
GL_REPLACE 用glStencilFunc函數所指定的參考值替換蒙板參數值
GL_INCR 增加當前的蒙板緩存區值,但限制在允許的范圍內
GL_DECR 減少當前的蒙板緩存區值,但限制在允許的范圍內
GL_INVERT 將當前的蒙板緩存區值進行逐位的翻轉

當完成了以上操作后我們繪制一個地面,當然現在你什么也看不到,它只是把覆蓋地面的蒙板緩存區中的相應位置設為1。
 
  

    glEnable(GL_STENCIL_TEST);                // 啟用蒙板緩存
    glStencilFunc(GL_ALWAYS, 1, 1);            // 設置蒙板測試總是通過,參考值設為1,掩碼值也設為1
    glStencilOp(GL_KEEP, GL_KEEP, GL_REPLACE);        // 設置當深度測試不通過時,保留蒙板中的值不變。如果通過則使用參考值替換蒙板值
    glDisable(GL_DEPTH_TEST);                // 禁用深度測試
    DrawFloor();                    // 繪制地面

  
 我們現在已經在蒙板緩存區中建立了地面的蒙板了,這是繪制影子的關鍵,如果想知道為什么,接著向后看吧:)
下面我們啟用深度測試和繪制顏色,并相應設置蒙板測試和函數的值,這種設置可以使我們在屏幕上繪制而不改變蒙板緩存區的值。
 
  

    glEnable(GL_DEPTH_TEST);                        //啟用深度測試
    glColorMask(1,1,1,1);                        // 可以繪制顏色
    glStencilFunc(GL_EQUAL, 1, 1);                    //下面的設置指定當我們繪制時,不改變蒙板緩存區的值
    glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);       
  
 下面的代碼設置并啟用剪切平面,使得只能在地面的下方繪制 
  

    glEnable(GL_CLIP_PLANE0);                        // 使用剪切平面
    glClipPlane(GL_CLIP_PLANE0, eqr);                    // 設置剪切平面為地面,并設置它的法線為向下
    glPushMatrix();                            // 保存當前的矩陣
        glScalef(1.0f, -1.0f, 1.0f);                // 沿Y軸反轉

  
 由于上面已經啟用了蒙板緩存,則你只能在蒙板中值為1的地方繪制,反射的實質就是在反射屏幕的對應位置在繪制一個物體,并把它放置在反射平面中。下面的代碼完成這個功能 
  

        glLightfv(GL_LIGHT0, GL_POSITION, LightPos);            // 設置燈光0
        glTranslatef(0.0f, height, 0.0f);               
        glRotatef(xrot, 1.0f, 0.0f, 0.0f);               
        glRotatef(yrot, 0.0f, 1.0f, 0.0f);               
        DrawObject();                        // 繪制反射的球
    glPopMatrix();                            // 彈出保存的矩陣
    glDisable(GL_CLIP_PLANE0);                        // 禁用剪切平面
    glDisable(GL_STENCIL_TEST);                        // 關閉蒙板

  
 下面的代碼繪制地面,并把地面顏色和反射的球顏色混合,使其看起來像反射的效果。 
  

    glLightfv(GL_LIGHT0, GL_POSITION, LightPos);
    glEnable(GL_BLEND);                            // 啟用混合
    glDisable(GL_LIGHTING);                            // 關閉光照
    glColor4f(1.0f, 1.0f, 1.0f, 0.8f);                        // 設置顏色為白色
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);                // 設置混合系數
    DrawFloor();                                // 繪制地面

  
 下面的代碼在距地面高為height的地方繪制一個真正的球 
  

    glEnable(GL_LIGHTING);                            // 使用光照
    glDisable(GL_BLEND);                            // 禁用混合
    glTranslatef(0.0f, height, 0.0f);                        // 移動高位height的位置
    glRotatef(xrot, 1.0f, 0.0f, 0.0f);                        // 設置球旋轉的角度
    glRotatef(yrot, 0.0f, 1.0f, 0.0f);                   
    DrawObject();                                // 繪制球

  
 下面的代碼用來處理鍵盤控制等常規操作 
  

    xrot += xrotspeed;                            // 更新X軸旋轉速度
    yrot += yrotspeed;                            // 更新Y軸旋轉速度
    glFlush();                            // 強制OpenGL執行所有命令
    return TRUE;                            // 成功返回
}

  
 下面的代碼處理鍵盤控制,上下左右控制球的旋轉。PageUp/Pagedown控制球的上下。A,Z控制球離你的遠近。 
  

void ProcessKeyboard()                               
{
    if (keys[VK_RIGHT])    yrotspeed += 0.08f;               
    if (keys[VK_LEFT])    yrotspeed -= 0.08f;               
    if (keys[VK_DOWN])    xrotspeed += 0.08f;               
    if (keys[VK_UP])    xrotspeed -= 0.08f;           

    if (keys['A'])        zoom +=0.05f;                   
    if (keys['Z'])        zoom -=0.05f;                   

    if (keys[VK_PRIOR])    height +=0.03f;                   
    if (keys[VK_NEXT])    height -=0.03f;                   
}

  
 KillGLWindow() 函數沒有任何改變 
  

GLvoid KillGLWindow(GLvoid)                           

  
 CreateGLWindow()函數基本沒有改變,只是添加了以行啟用蒙板緩存 
  

    static    PIXELFORMATDESCRIPTOR pfd=
    {
        sizeof(PIXELFORMATDESCRIPTOR),                   
        1,                               
        PFD_DRAW_TO_WINDOW |                       
        PFD_SUPPORT_OPENGL |                   
        PFD_DOUBLEBUFFER,                       
        PFD_TYPE_RGBA,                       
        bits,                               
        0, 0, 0, 0, 0, 0,                       
        0,                               
        0,                           
        0,                               
        0, 0, 0, 0,                           
        16,                           
  
 下面就是在這個函數中唯一改變的地方,記得把0變為1,它啟用蒙板緩存。 
  

        1,                                // 使用蒙板緩存
        0,                               
        PFD_MAIN_PLANE,                           
        0,                               
        0, 0, 0                               
    };

  
 WinMain()函數基本沒有變化,只是加上以行鍵盤控制的處理函數 
  

                    ProcessKeyboard();            // 處理按鍵相應

  
 我真的希望你能喜歡這個教程,我清楚地知道我想做的每一件事,以及如何一步一步實現我心中想創建的效果。但把它表達出來又是另一回事,當你坐下來并實際的去向那些從來沒聽到過蒙板緩存的人解釋這一切時,你就會清楚了。好了,如果你有什么不清楚的,或者有更好的建議,請讓我知道,我想些最好的教程,你的反饋很重要!
 


posted on 2007-12-19 11:47 sdfasdf 閱讀(1412) 評論(0)  編輯 收藏 引用 所屬分類: OPENGL
青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            欧美韩日一区二区三区| 国产欧美精品va在线观看| 亚洲国产高清一区| 欧美中文字幕在线播放| 亚洲专区一区| 欧美亚洲在线播放| 久久精品99国产精品酒店日本| 午夜精品一区二区在线观看| 亚洲免费在线| 久久久久久69| 欧美激情成人在线| 一区二区三区成人精品| 亚洲免费在线观看| 久久久免费精品视频| 欧美不卡高清| 国产精品男女猛烈高潮激情| 国产主播精品在线| 夜夜狂射影院欧美极品| 久久国产精品毛片| 亚洲三级影院| 午夜久久影院| 欧美精品成人91久久久久久久| 国产精品成人久久久久| 亚洲第一成人在线| 亚洲欧美国产高清| 欧美黄色日本| 亚洲一区二区精品视频| 免费视频一区| 国产永久精品大片wwwapp| 99re66热这里只有精品3直播| 欧美夜福利tv在线| 亚洲欧洲在线观看| 久久人人超碰| 国产农村妇女毛片精品久久莱园子 | 亚洲视频在线观看三级| 久久久久久久一区二区| 欧美日韩午夜剧场| 亚洲国产欧美一区二区三区久久| 亚洲欧美bt| 亚洲国产一区二区a毛片| 欧美专区在线观看一区| 欧美性猛交视频| 亚洲国产综合91精品麻豆| 欧美一区二区三区免费看| 亚洲乱码国产乱码精品精天堂| 欧美亚洲色图校园春色| 国产精品成人一区二区三区吃奶 | 欧美承认网站| 久久久夜夜夜| 亚洲一区二区三区777| 欧美国产欧美亚洲国产日韩mv天天看完整| 国产欧美精品在线| 亚洲男人的天堂在线| 亚洲国产美女精品久久久久∴| 欧美亚洲视频在线观看| 国产精品久久久一区麻豆最新章节 | av不卡在线| 女人色偷偷aa久久天堂| 激情成人中文字幕| 欧美专区在线| 午夜国产一区| 国产一区二区| 久久综合九色| 久久夜色精品国产亚洲aⅴ| 国产一区二区精品在线观看| 欧美亚洲免费电影| 午夜精品三级视频福利| 国产精品自拍三区| 性视频1819p久久| 欧美亚洲色图校园春色| 狠狠色伊人亚洲综合网站色| 久久久久一区二区三区| 久久蜜桃香蕉精品一区二区三区| 国产最新精品精品你懂的| 久久网站免费| 免费观看久久久4p| 一本久久a久久精品亚洲| 亚洲特黄一级片| 狠狠色综合网站久久久久久久| 欧美高清视频在线观看| 欧美多人爱爱视频网站| 亚洲午夜一区二区三区| 欧美亚洲在线播放| 亚洲福利视频在线| 中日韩午夜理伦电影免费| 国产亚洲综合在线| 亚洲电影网站| 国产精品sm| 久久综合久久综合久久综合| 欧美成人精品激情在线观看| 亚洲欧美在线观看| 久久亚洲精选| 午夜精品短视频| 免播放器亚洲一区| 亚洲欧美日韩综合| 久热综合在线亚洲精品| 亚洲一级片在线观看| 久久aⅴ国产紧身牛仔裤| 亚洲精品国产精品国自产在线| 亚洲少妇最新在线视频| 伊人春色精品| 正在播放欧美视频| 亚洲欧洲视频| 亚洲在线成人精品| 91久久精品一区二区别| 国产精品久久国产精品99gif| 亚洲天堂第二页| 久久不射电影网| 一区二区三区四区五区精品视频 | 亚洲欧美日韩国产成人精品影院| 一区在线影院| 亚洲小视频在线| 亚洲精品日韩综合观看成人91| 亚洲欧美日本另类| 夜夜嗨av一区二区三区网页| 久久成年人视频| 亚洲影视在线播放| 欧美刺激午夜性久久久久久久| 久久久之久亚州精品露出| 欧美日韩在线播放一区二区| 欧美成人午夜免费视在线看片| 国产人成精品一区二区三| 亚洲大片av| 国产欧美日韩一级| 一区二区三区波多野结衣在线观看| 亚洲激情午夜| 久久久久女教师免费一区| 亚洲欧美一区二区激情| 欧美日韩综合在线| 亚洲另类春色国产| 一本久久a久久精品亚洲| 久久国产高清| 久久久久免费观看| 一区二区三区我不卡| 性欧美长视频| 久久精品国产精品亚洲精品| 国产精品免费福利| 亚洲一区中文字幕在线观看| 亚洲一区免费网站| 欧美午夜精品久久久| 夜夜爽夜夜爽精品视频| 亚洲午夜一区二区三区| 国产精品久久久久久久久久ktv| 亚洲理论在线| 亚洲欧美中文字幕| 国产欧美欧美| 午夜久久tv| 男女视频一区二区| 亚洲激情专区| 欧美激情在线| 亚洲伊人伊色伊影伊综合网 | 欧美在线一区二区三区| 国产精品美女久久久| 日韩一级网站| 国产欧美精品xxxx另类| 久久久久久久久伊人| 亚洲欧洲精品成人久久奇米网| 99精品欧美一区| 欧美日韩专区在线| 午夜精品久久久久久久白皮肤| 久久精品国产清自在天天线| 伊人久久大香线蕉av超碰演员| 欧美成人午夜激情视频| 99re热精品| 久久精品综合| 9l国产精品久久久久麻豆| 国产精品美女午夜av| 久久精品成人一区二区三区| 亚洲成色最大综合在线| 性久久久久久久久久久久| 红杏aⅴ成人免费视频| 欧美成人免费在线观看| 欧美日韩国产精品一卡| 亚洲欧美电影院| 久久久人成影片一区二区三区| 亚洲第一中文字幕在线观看| 欧美日韩人人澡狠狠躁视频| 欧美专区福利在线| 欧美激情国产日韩| 欧美一区二区免费| 日韩视频一区二区在线观看 | 在线色欧美三级视频| 欧美三级网页| 久久最新视频| 欧美一区二区三区免费观看视频| 午夜在线精品| 亚洲人永久免费| 国内精品久久久久久久果冻传媒| 欧美理论电影网| 久久大逼视频| 一区二区三区精品视频在线观看| 免费日韩av电影| 欧美在线亚洲在线| 亚洲在线黄色| 一区国产精品| 国产精品影视天天线| 欧美好骚综合网| 久久亚洲国产精品一区二区| 午夜精品三级视频福利| 亚洲一区二区三区午夜|