亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Delphi > 正文

NeHe的opengl教程delphi版(8)----簡單的透明

2019-11-18 18:30:21
字體:
來源:轉載
供稿:網友
 

{

呵呵,這兩課早就翻譯好了,一直沒貼,大家久等了(有人再等嗎?)

簡單的透明
OpenGL中的絕大多數特效都與某些類型的(色彩)混合有關。
混色的定義為,將某個象素的顏色和已繪制在屏幕上與其對應的象素顏色相互結合。
至于如何結合這兩個顏色則依賴于顏色的alpha通道的分量值,以及/或者所使用的混色函數。
Alpha通常是位于顏色值末尾的第4個顏色組成分量。
前面這些課我們都是用GL_RGB來指定顏色的三個分量。
相應的GL_RGBA可以指定alpha分量的值。
更進一步,我們可以使用glColor4f()來代替glColor3f()。

絕大多數人都認為Alpha分量代表材料的透明度。
這就是說,alpha值為0.0時所代表的材料是完全透明的。
alpha值為1.0時所代表的材料則是完全不透明的。

混色的公式
若您對數學不感冒,而只想看看如何實現透明,請跳過這一節。
若您想深入理解(色彩)混合的工作原理,這一節應該適合您吧。
『CKER的補充:其實并不難^-^。原文中的公式如下,CKER再嘮叨一下吧。
其實混合的基本原理是就將要分色的圖像各象素的顏色以及背景顏色均按照RGB規則各自分離之后,
根據-圖像的RGB顏色分量*alpha值+背景的RGB顏色分量*(1-alpha值)
-這樣一個簡單公式來混合之后,最后將混合得到的RGB分量重新合并?!?/P>

公式如下:
(Rs Sr + Rd Dr, Gs Sg + Gd Dg, Bs Sb + Bd Db, As Sa + Ad Da)
OpenGL按照上面的公式計算這兩個象素的混色結果。
小寫的s和r分別代表源象素和目標象素。大寫的S和D則是相應的混色因子。
這些決定了您如何對這些象素混色。
絕大多數情況下,各顏色通道的alpha混色值大小相同,
這樣對源象素就有 (As, As, As, As),
目標象素則有1, 1, 1, 1) - (As, As, As, As)。
上面的公式就成了下面的模樣:
(Rs As + Rd (1 - As), Gs As + Gd (1 - As), Bs As + Bs (1 - As), As As + Ad (1 - As))
這個公式會生成透明/半透明的效果。

OpenGL中的混色
在OpenGL中實現混色的步驟類似于我們以前提到的OpenGL過程。
接著設置公式,并在繪制透明對象時關閉寫深度緩存。
因為我們想在半透明的圖形背后繪制 對象。
這不是正確的混色方法,但絕大多數時候這種做法在簡單的項目中都工作的很好。

Rui Martins 的補充: 正確的混色過程應該是先繪制全部的場景之后再繪制透明的圖形。
并且要按照與深度緩存相反的次序來繪制(先畫最遠的物體)。
考慮對兩個多邊形(1和2)進行alpha混合,不同的繪制次序會得到不同的結果。
(這里假定多邊形1離觀察者最近,那么正確的過程應該先畫多邊形2,再畫多邊形1。
正如您再現實中所見到的那樣,
從這兩個<透明的>多邊形背后照射來的光線總是先穿過多邊形2,
再穿過多邊形1,最后才到達觀察者的眼睛。)
在深度緩存啟用時,您應該將透明圖形按照深度進行排序,
并在全部場景繪制完畢之后再繪制這些透明物體。否則您將得到不正確的結果。
我知道某些時候這樣做是很令人痛苦的,但這是正確的方法。

我們將使用第七課的代碼。
一開始先在代碼開始處增加兩個新的變量。出于清晰起見,我重寫了整段代碼。

}
Var
   h_RC             : HGLRC;            // Rendering Context(著色描述表)。
   h_DC             : HDC;              // Device Context(設備描述表)
   h_Wnd            : HWND;             // 窗口句柄
   h_Instance       : HINST;            // 程序Instance(實例)。
   keys             : Array[0..255] Of Boolean; // 用于鍵盤例程的數組

   light            : Boolean;          // 光源的開/關

   blend            : Boolean;          // Blending OFF/ON? ( 新增 )

   lp               : Boolean;          // L鍵按下了么?
   fp               : Boolean;          // F鍵按下了么?

   bp               : Boolean;          // B 鍵按下了么? ( 新增 )

   xrot             : GLfloat;          // X 旋轉
   yrot             : GLfloat;          // Y 旋轉
   xspeed           : GLfloat;          // X 旋轉速度
   yspeed           : GLfloat;          // Y 旋轉速度

   z                : GLfloat = -5.0 f; // 深入屏幕的距離
   LightAmbient     : Array[0..3] Of GLfloat = (0.5, 0.5, 0.5, 1.0);  //環境光參數 ( 新增 )
   LightDiffuse     : Array[0..3] Of GLfloat = (1.0, 1.0, 1.0, 1.0);  // 漫射光參數 ( 新增 )
   LightPosition    : Array[0..3] Of GLfloat = (0.0, 0.0, 2.0, 1.0);  // 光源位置 ( 新增 )
   filter           : GLuint;           // 濾波類型
   texture          : Array[0..2] Of GLuint; // 3種紋理的儲存空間

PRocedure glGenTextures(n: GLsizei; Var textures: GLuint); stdcall; external
   opengl32;

Procedure glBindTexture(target: GLenum; texture: GLuint); stdcall; external
   opengl32;

Function gluBuild2DMipmaps(target: GLenum; components, width, height: GLint;
   format, atype: GLenum; data: Pointer): Integer; stdcall; external glu32 name
   'gluBuild2DMipmaps';

{
然后往下移動到 LoadGLTextures() 這里。
找到 if (TextureImage[0]=LoadBMP('Data/Crate.bmp'))
這一行。我們現在使用有色玻璃紋理來代替上一課中的木箱紋理。
if (TextureImage[0]=LoadBMP("Data/glass.bmp")); // 載入玻璃位圖 ( 已修改 )
}

Function LoadTexture: boolean;          // 載入位圖并轉換成紋理
Var
   Status           : boolean;          // Status 指示器
   TextureImage     : Array[0..1] Of PTAUX_RGBImageRec; // 創建紋理的存儲空間
Begin
   Status := false;
   ZeroMemory(@TextureImage, sizeof(TextureImage)); // 將指針設為 NULL
   TextureImage[0] := LoadBMP('Walls.bmp');
   If TextureImage[0] <> Nil Then
      Begin
         Status := TRUE;                // 將 Status 設為 TRUE
         glGenTextures(1, texture[0]);  // 創建紋理
         // 創建 Nearest 濾波貼圖
         glBindTexture(GL_TEXTURE_2D, texture[0]);
         // 生成紋理
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);  // ( 新增 )
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  // ( 新增 )

         glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
            TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
            TextureImage[0].data);
         glBindTexture(GL_TEXTURE_2D, texture[1]);  // 使用來自位圖數據生成 的典型紋理
         // 生成紋理
         glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0].sizeX,
            TextureImage[0].sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE,
            TextureImage[0].data);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);  // 線形濾波
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  // 線形濾波
         // 創建 MipMapped 紋理
         glBindTexture(GL_TEXTURE_2D, texture[2]);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER,
            GL_LINEAR_MIPMAP_NEAREST);  // ( 新增 )
         gluBuild2DMipmaps(GL_TEXTURE_2D, 3, TextureImage[0].sizeX,
            TextureImage[0].sizey, GL_RGB, GL_UNSIGNED_BYTE,
            TextureImage[0].data);      //(新增)  }
      End;
   If assigned(TextureImage[0]) Then    // 紋理是否存在
      If assigned(TextureImage[0].data) Then // 紋理圖像是否存在
         TextureImage[0].data := Nil;   // 釋放紋理圖像占用的內存
   TextureImage[0] := Nil;              // 釋放圖像結構
   result := Status;                    // 返回 Status
End;

{
在glInit()代碼段加入以下兩行。
第一行以全亮度繪制此物體,并對其進行50%的alpha混合(半透明)。
當混合選項打開時,此物體將會產生50%的透明效果。
第二行設置所采用的混合類型。

Rui Martins 的補充:
alpha通道的值為 0.0意味著物體材質是完全透明的。
1.0 則意味著完全不透明。
}

Procedure glInit();                     // 此處開始對OpenGL進行所有設置
Begin
   If (Not LoadTexture) Then            // 調用紋理載入子例程
      exit;                             // 如果未能載入,退出

   glEnable(GL_TEXTURE_2D);             // 啟用紋理映射
   glShadeModel(GL_SMOOTH);             // 啟用陰影平滑
   glClearColor(0.0, 0.0, 0.0, 0.0);    // 黑色背景
   glClearDepth(1.0);                   // 設置深度緩存
   glEnable(GL_DEPTH_TEST);             // 啟用深度測試
   glDepthFunc(GL_LESS);                // 所作深度測試的類型
   glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); //高度優化的透視投影計算
   glLightfv(GL_LIGHT1, GL_AMBIENT, @LightAmbient[0]); // 設置環境光
   glLightfv(GL_LIGHT1, GL_DIFFUSE, @LightDiffuse[0]); // 設置漫射光
   glLightfv(GL_LIGHT1, GL_POSITION, @LightPosition); // 光源位置
   glEnable(GL_LIGHT1);                 // 啟用一號光源

   glColor4f(1.0, 1.0, 1.0, 0.5);       // 全亮度, 50% Alpha 混合( 新增 )
   glBlendFunc(GL_SRC_ALPHA, GL_ONE); // 基于源象素alpha通道值的半透明混合函數 ( 新增 )

End;

 {在接近第七課結尾處的地方找到下面的代碼段。
                  If keys[VK_LEFT] Then    //Left方向鍵按下了么?
                  yspeed := yspeed - 0.01; //若是, 減少yspeed
                接著上面的代碼,我們增加如下的代碼。
                這幾行監視B鍵是否按下。
                如果是的話,計算機檢查混合選項是否已經打開。
                然后將其置為相反的狀態。
                }
               If (keys[ord('B')] And Not bp) Then //B 健按下且bp為 FALSE么?
                  Begin
                     bp := TRUE;        // 若是, bp 設為 TRUE
                     blend := Not blend; // 切換混合選項的 TRUE / FALSE
                     If (blend) Then    // 混合打開了么?
                        Begin
                           glEnable(GL_BLEND); // 打開混合
                           glDisable(GL_DEPTH_TEST); // 關閉深度測試
                        End
                     Else               // 否則
                        Begin
                           glDisable(GL_BLEND); // 關閉混合
                           glEnable(GL_DEPTH_TEST); // 打開深度測試
                        End;
                  End;
               If (Not keys[ord('B')]) Then //  B 鍵松開了么?
                  Begin
                     bp := FALSE;       // 若是, bp設為 FALSE
                  End;
               {
               但是怎樣才能在使用紋理貼圖的時候指定混合時的顏色呢?很簡單,
               在調整貼圖模式時,文理貼圖的每個象素點的顏色都是由alpha通道參數
               與當前地象素顏色相乘所得到的。
               比如,繪制的顏色是 (0.5, 0.6, 0.4),
               我們會把顏色相乘得到(0.5, 0.6, 0.4, 0.2)
                (alpha參數在沒有指定時,缺省為零)。
               就是如此!OpenGL實現Alpha混合的確很簡單!
               }
               {
                原文注 (11/13/99)
                我(NeHe)混色代碼進行了修改,以使顯示的物體看起來更逼真。
                同時對源象素和目的象素使用alpha參數來混合,會導致物體的人造痕跡看起來很明顯。
                會使得物體的背面沿著側面的地方顯得更暗。
                基本上物體會看起來很怪異。
                我所用的混色方法也許不是最好的,但的確能夠工作。
                啟用光源之后,物體看起來很逼真。
                感謝Tom提供的原始代碼,他采用的混色方法是正確的,
                但物體看起來并不象所期望的那樣吸引人:)
                代碼所作的再次修改是因為在某些顯卡上glDepthMask()函數存在尋址問題。
                這條命令在某些卡上啟用或關閉深度緩沖測試時似乎不是很有效,
                所以我已經將啟用或關閉深度緩沖測試的代碼轉成老式的glEnable和glDisable。

                紋理貼圖的Alpha混合
                用于紋理貼圖的alpha參數可以象顏色一樣從問題貼圖中讀取。
                方法如下,您需要在載入所需的材質同時取得其的alpha參數。
                然后在調用glTexImage2D()時使用GL_RGBA的顏色格式。
               }


上一篇:NeHe的opengl教程delphi版(9)----星星

下一篇:Delphi代碼創建形式規范

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
學習交流
熱門圖片

新聞熱點

疑難解答

圖片精選

網友關注

亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国内精品久久影院| 91免费电影网站| 亚洲白虎美女被爆操| 日本道色综合久久影院| 精品国产成人在线| 国产精品影片在线观看| 啊v视频在线一区二区三区| 国产精品成人aaaaa网站| 欧美一性一乱一交一视频| 这里只有精品在线播放| 日韩专区在线观看| 久久精品91久久久久久再现| xvideos成人免费中文版| 亚洲已满18点击进入在线看片| 国产成人久久精品| 日韩欧美国产网站| 26uuu日韩精品一区二区| 中文字幕av一区二区三区谷原希美| 在线观看日韩av| 欧美激情日韩图片| 欧美国产在线视频| 欧美日韩中国免费专区在线看| 国产精品美女在线观看| 欧美专区中文字幕| 亚洲欧美日韩成人| 精品久久久中文| 日韩美女视频中文字幕| 亚洲人成77777在线观看网| 日韩性生活视频| 国产美女91呻吟求| 国产欧美日韩中文字幕在线| 亚洲欧美福利视频| 久久久久久九九九| 日韩av综合网| 自拍偷拍亚洲一区| 亚洲久久久久久久久久| 国产精品日本精品| 国产精品午夜视频| 久久久久久久久久亚洲| 亚洲伊人久久大香线蕉av| 国产午夜精品一区理论片飘花| 另类少妇人与禽zozz0性伦| 久久久免费在线观看| 日本亚洲精品在线观看| 亚洲成avwww人| 日韩电视剧在线观看免费网站| 7777精品视频| 久久成人国产精品| 国产午夜精品全部视频在线播放| 亚洲综合第一页| 国产色综合天天综合网| 91精品久久久久久久久久久| 国产综合福利在线| 亚洲一区二区三区777| 欧美性猛交xxxx富婆| 夜夜嗨av一区二区三区四区| 亚洲男女自偷自拍图片另类| 国产99视频在线观看| 午夜精品久久久久久久99黑人| 久久久久久成人| 欧美性开放视频| 国产精品久久久久久久久久| 亚洲国产精品女人久久久| 成人激情在线观看| 在线观看欧美日韩国产| 亚洲国产私拍精品国模在线观看| 国产主播在线一区| 伊人一区二区三区久久精品| 亚洲片av在线| 国产精品亚洲网站| 亚洲天堂av图片| 亚洲在线免费视频| 欧美色道久久88综合亚洲精品| 中文字幕亚洲第一| 国产精品揄拍一区二区| 亚州成人av在线| 国产91精品青草社区| 国产丝袜精品视频| 精品国产一区二区三区四区在线观看| 亚洲国产精品久久久久秋霞不卡| 亚洲精品国产精品国自产在线| 国产精品久久久久久久久免费看| 久久躁日日躁aaaaxxxx| 久久精品视频播放| 久久久精品在线| 欧美激情精品久久久久久久变态| 91免费福利视频| 亚洲免费影视第一页| 久久久精品免费视频| 欧美日韩精品在线观看| 亚洲欧美日韩一区二区在线| 夜夜躁日日躁狠狠久久88av| 中文字幕精品影院| 国产福利成人在线| 91午夜理伦私人影院| 一区二区三区国产视频| 色偷偷9999www| 隔壁老王国产在线精品| 超碰91人人草人人干| 亚洲免费影视第一页| 国产精品热视频| 久久精品99久久久久久久久| 亚洲第一区在线观看| 欧美最猛黑人xxxx黑人猛叫黄| 国产91热爆ts人妖在线| 91精品国产综合久久久久久久久| 91精品国产高清久久久久久91| 国产97色在线| 精品自在线视频| 亚洲欧美日本另类| 美女福利视频一区| 5566日本婷婷色中文字幕97| 久久久之久亚州精品露出| 国产精品网红福利| 亚洲人成网站777色婷婷| 久久影视三级福利片| xvideos成人免费中文版| 国产精品视频公开费视频| 欧美黑人xxx| 欧美国产日韩一区| 欧美第一淫aaasss性| 欧美午夜性色大片在线观看| 97在线视频免费观看| 国产精品88a∨| 欧美精品免费播放| 亚洲欧美综合区自拍另类| 精品亚洲aⅴ在线观看| 欧美国产日韩一区二区在线观看| 亚洲免费福利视频| 国产999精品| 美女av一区二区三区| 欧美中文字幕在线视频| 欧美激情伊人电影| 国产69精品久久久久久| 成人黄色中文字幕| 久久久久久久久中文字幕| 欧美资源在线观看| 久久成人18免费网站| 色综合天天狠天天透天天伊人| 亚洲国产精品资源| 欧美黑人xxxⅹ高潮交| 国产成人精品一区二区| 欧美日韩裸体免费视频| 欧美另类69精品久久久久9999| 国产成人高潮免费观看精品| 国产精品久久久| 亚洲一区二区三区四区视频| 成人免费视频97| 亚洲欧美中文另类| 亚洲电影免费观看| 欧美性生交大片免费| 91久久精品国产91久久性色| 国产成人av在线| 俺去亚洲欧洲欧美日韩| 亚洲18私人小影院| 欧美性猛交xxxx免费看漫画| 成人免费在线网址| 成人国内精品久久久久一区| …久久精品99久久香蕉国产| 国产一区玩具在线观看| 欧美日韩中文字幕综合视频| 欧美视频裸体精品| 亚洲欧洲xxxx| 久久不射热爱视频精品|