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

WisKeyのLullaby

huangwei.pro 『我失去了一只臂膀』「就睜開了一只眼睛」

  C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
  12 Posts :: 0 Stories :: 23 Comments :: 0 Trackbacks

公告

“我該走哪條路?”
“這取決于你要去哪里?!?br> “我只想能到某個地方。”
“只要你走的夠遠,你始終能到達那個地方?!?br>

Home: huangwei.pro
E-Mail: sir.huangwei [at] gmail.com
09.6 畢業于杭州電子科技大學
進入網易杭州研究院工作至今

常用鏈接

留言簿(1)

我參與的團隊

搜索

  •  

積分與排名

  • 積分 - 51753
  • 排名 - 447

最新評論

閱讀排行榜

評論排行榜

http://huangwei.pro/2015-08/modern-opengl2/

 

在本文中,我們將給三角形加一個貼圖,這需要在頂點和片段著色器中加入一些新變量,創建和使用貼圖對象,并且學習一點貼圖單元和貼圖坐標的知識。

本文會使用兩個新的類到tdogl命名空間中:tdogl:Bitmaptdogl:Texture。這些類允許我們將jpg,png或bmp圖片上傳到顯存并用于著色器。tdogl:Program類也增加一些相關接口。

獲取代碼

所有例子代碼的zip打包可以從這里獲?。?a style="box-sizing: border-box; color: #428bca; text-decoration: none; background: transparent;">https://github.com/tomdalling/opengl-series/archive/master.zip。

這一系列文章中所使用的代碼都存放在:https://github.com/tomdalling/opengl-series。你可以在頁面中下載zip,加入你會git的話,也可以復制該倉庫。

本文代碼你可以在source/02_textures目錄里找到。使用OS X系統的,可以打開根目錄里的opengl-series.xcodeproj,選擇本文工程。使用Windows系統的,可以在Visual Studio 2013里打開opengl-series.sln,選擇相應工程。

工程里已包含所有依賴,所以你不需要再安裝或者配置額外的東西。如果有任何編譯或運行上的問題,請聯系我。

著色器變量Uniform與Attribute

教程一里的著色器變量都是attribute,本文介紹另外一種類型的變量:uniform變量。

著色器變量有兩種類型:uniformattribute。attribute變量可以在每個頂點上有不同值。而uniform變量在多個頂點上保持相同值。比如,你想要給一個三角形設置一種顏色,那你應該使用uniform變量,如果你希望每個三角形頂點有不同顏色,你應該使用attribute變量。從這開始,我稱呼他們為“uniforms”和“attributes”。

Uniforms能被任意著色器訪問,但是Attributes必須先進入頂點著色器,而非片段著色器。頂點著色器在需要時會將該值傳給片段著色器。這因為Uniforms像常量-它們不會被任何著色器更改。然而,Attributes不是常量。頂點著色器會改變Attribute變量的值,在片段著色器獲取之前。就是說,頂點著色器的輸出就是片段著色器的輸入。

為了設置Uniform的值,我們可以調用glUniform*系列函數。而設置Attribute的值,我們需要在VBO中保存,并且和VAO一起發送給著色器,就像前一篇教程里的glVertexAttribPointer。加入你不想把值存在VBO里,你也可以使用glVertexAttrib*系列函數來設置Attribute值。

貼圖

貼圖,大體上來說就是你應用在3D物體上的2D圖像。它有其它用途,但顯示2D圖像在3D幾何上是最常用的。有1D,2D,3D貼圖,但本文只講2D貼圖。更深入閱讀,請參見Learning Modern 3D Graphics Programming書中的Textures are not Pictures章節。

貼圖是存放在顯存里的。那就是說,你需要在使用之前上傳你的貼圖數據給顯卡。這類似VBO在前文的作用-VBO也是在使用之前需要存放到顯存上。

貼圖的高和寬需要是2的冪次方。比如16,32,64,128,256,512。本文中使用的是256*256的圖像作為貼圖,如下圖所示。

hazard.png

 

我們使用tdogl:Bitmap來加載“hazard.png”的原始像素數據到內存中,參見stb_image幫助文檔。然后我們使用tdogl:Texture上傳原始像素數據給OpenGL貼圖對象。幸運的是OpenGL中的貼圖創建方法從面世到現在都沒有實質性的變化,所以網上有大量的創建貼圖的好文章。雖然貼圖坐標的傳輸方式有變化,但創建貼圖還是跟以前一樣。

以下是tdogl:Texture的構造函數,用于OpenGL貼圖創建。

Texture::Texture(const Bitmap& bitmap, GLint minMagFiler, GLint wrapMode) : _originalWidth((GLfloat)bitmap.width()), _originalHeight((GLfloat)bitmap.height()) { glGenTextures(1, &_object); glBindTexture(GL_TEXTURE_2D, _object); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minMagFiler); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, minMagFiler); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrapMode); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrapMode); glTexImage2D(GL_TEXTURE_2D, 0, TextureFormatForBitmapFormat(bitmap.format()), (GLsizei)bitmap.width(), (GLsizei)bitmap.height(), 0, TextureFormatForBitmapFormat(bitmap.format()), GL_UNSIGNED_BYTE, bitmap.pixelBuffer()); glBindTexture(GL_TEXTURE_2D, 0); } 

貼圖坐標

毫無疑問,貼圖坐標就是貼圖上的坐標。關于貼圖坐標比較奇特的是它們不是以像素為單位。它們范圍是從0到1,(0, 0)是左下角,(1, 1)是右上角。假如你上傳到OpenGL的圖像是顛倒的,那(0, 0)就是左上角,而非左下角。將像素坐標轉換為貼圖坐標,你必須除上貼圖的寬和高。比如,在256*256的圖像中,像素坐標(128, 256)的貼圖坐標是(0.5, 1)。

uv_coords.png

 

貼圖坐標通常被稱為UV坐標。你也可以叫它們是XY坐標,但是XYZ通常被用來表示頂點,我們不希望將這兩者混淆。

貼圖圖像單元

貼圖圖像單元,亦或簡稱“貼圖單元”,是在OpenGL中略怪異的一部分。你無法直接發送貼圖給著色器。首先,你要綁定貼圖到貼圖單元,然后呢要發送貼圖單元的索引給著色器

對于貼圖單元是有數量限制的。在低端硬件上,如手機,它們只有兩個貼圖單元。既然如此,即使我們有許多的貼圖,我們也只能同時使用兩個貼圖單元在著色器中。我們在本文中只用到了一個貼圖,所以也只需要一個貼圖單元,但它可以在多個不同的著色器中混合。

實現貼圖

首先,讓我們創建一個新的全局貼圖。

tdogl::Texture* gTexture = NULL; 

我們為加載“hazard.png”圖片新增一個函數。該函數能被AppMain所調用。

static void LoadTexture() { tdogl::Bitmap bmp = tdogl::Bitmap::bitmapFromFile(ResourcePath("hazard.png")); bmp.flipVertically(); gTexture = new tdogl::Texture(bmp); } 

下一步,我們給每個三角形的頂點一個貼圖坐標。假如你跟上圖比較過UV坐標,就可以看出按順序這個坐標表示(中,上),(左,下)和(右,下)。

GLfloat vertexData[] = { //  X     Y     Z       U     V 0.0f, 0.8f, 0.0f, 0.5f, 1.0f, -0.8f,-0.8f, 0.0f, 0.0f, 0.0f, 0.8f,-0.8f, 0.0f, 1.0f, 0.0f, }; 

現在我們需要修改片段著色器,使得它能使用貼圖和貼圖坐標作為輸入。下面是新的片段著色器代碼:

#version 150 uniform sampler2D tex; //this is the texture in vec2 fragTexCoord; //this is the texture coord out vec4 finalColor; //this is the output color of the pixel  void main() { finalColor = texture(tex, fragTexCoord); } 

uniform關鍵字說明texuniform變量。貼圖是一致的,因為所有三角形頂點有相同的貼圖。sampler2D是變量類型,說明它包含一個2D貼圖。

fragTexCoordattribute變量,因為每個三角形頂點是不同的貼圖坐標。

texture函數是用來查找給定貼圖坐標的像素顏色。在GLSL舊版本中,你應該使用texture2D函數來實現該功能。

我們無法直接傳送attribute給判斷著色器,因為attribute必須首先通過頂點著色器。這兒是修改過的頂點著色器:

#version 150 in vec3 vert; in vec2 vertTexCoord; out vec2 fragTexCoord;  void main() { // Pass the tex coord straight through to the fragment shader fragTexCoord = vertTexCoord; gl_Position = vec4(vert, 1); } 

頂點著色器使用vertTexCoord作為輸入,并且將它不經修改,直接傳給名為fragTexCoordattribute片段著色器變量。

著色器有兩個變量需要我們設置:vertTexCoordattribute變量和texuniform變量。讓我們從設置tex變量開始。打開main.cpp,找到Render()函數。我們在繪制三角形之前設置texuniform變量:

glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, gTexture->object()); gProgram->setUniform("tex", 0); //set to 0 because the texture is bound to GL_TEXTURE0 

貼圖在沒有綁定到貼圖單元時,是無法使用的。glActiveTexture告訴OpenGL我們希望使用哪個貼圖單元。GL_TEXTURE0是第一個貼圖單元,我們就使用它。

下一本,我們使用glBindTexture來綁定我們的貼圖到激活的貼圖單元。

然后我們設置貼圖單元索引給texuniform著色器變量。我們使用0號貼圖單元,所以我們設置tex變量為整數0。setUniform方法只是調用了glUnifrom1i函數。

最后一步,獲取貼圖坐標給vertTexCoordattribute變量。為了實現它,我們需要修改LoadTriangle()函數中的VAO。之前的代碼是這樣的:

// Put the three triangle vertices into the VBO GLfloat vertexData[] = { //  X     Y     Z 0.0f, 0.8f, 0.0f, -0.8f,-0.8f, 0.0f, 0.8f,-0.8f, 0.0f };  // connect the xyz to the "vert" attribute of the vertex shader glEnableVertexAttribArray(gProgram->attrib("vert")); glVertexAttribPointer(gProgram->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 0, NULL); 

現在我們需要改成這樣:

// Put the three triangle vertices (XYZ) and texture coordinates (UV) into the VBO GLfloat vertexData[] = { //  X     Y     Z       U     V 0.0f, 0.8f, 0.0f, 0.5f, 1.0f, -0.8f,-0.8f, 0.0f, 0.0f, 0.0f, 0.8f,-0.8f, 0.0f, 1.0f, 0.0f, };  // connect the xyz to the "vert" attribute of the vertex shader glEnableVertexAttribArray(gProgram->attrib("vert")); glVertexAttribPointer(gProgram->attrib("vert"), 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), NULL);  // connect the uv coords to the "vertTexCoord" attribute of the vertex shader glEnableVertexAttribArray(gProgram->attrib("vertTexCoord")); glVertexAttribPointer(gProgram->attrib("vertTexCoord"), 2, GL_FLOAT, GL_TRUE, 5*sizeof(GLfloat), (const GLvoid*)(3 * sizeof(GLfloat))); 

我們第二次調用了glVertexAttribPointer,但我們也修改了第一個調用。最重要的是最后兩個參數。

兩個glVertexAttribPointer調用的倒數第二個參數都是5*sizeof(GLfloat)。這是“步長”參數。該參數是表明每個值開始位置的間隔是多少字節,或者說是到下個值開始的字節數。在兩個調用中,每個值是5個GLFloat長度。舉個例子,加入我們從“X”開始,往前數5個值,我們會落在下個“X”值上。從“U”開始也一樣,也是往前數5個。該參數是字節單位,不是浮點作為單位,所以我們必須乘上浮點類型所占字節數。

最后一個參數glVertexAttribPointer是一個“偏移”參數。該參數需要知道從開始到第一個值有多少字節。開始是XYZ,所以偏移設置為NULL表示“到開始的距離為0字節”。第一個UV不在最前面-中間有3個浮點的距離。再說一遍,參數是以字節為單位,而非浮點,所以我們必須乘上浮點類型所占字節數。并且我們必須將數值轉為const GLvoid*類型,因為在舊版本的OpenGL中該參數有別于現在的“偏移”。

現在,當你運行程序,你就能看到如本文最上方的那個三角形。

下篇預告

下一篇教程中我們會學一些矩陣相關的東西,使用矩陣來旋轉立方體,移動相機,和添加透視投影。我們還會學習深度緩沖和基于時間更新的邏輯,比如動畫。

更多OpenGL貼圖相關資源

posted on 2015-08-06 20:17 威士忌 閱讀(1633) 評論(1)  編輯 收藏 引用

Feedback

# re: 現代OpenGL教程 02 - 貼圖 2015-12-01 17:13 mmocake
給三角形加一個貼圖,學習了,MARK下  回復  更多評論
  

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产精品v一区二区三区| 亚洲精品视频一区| 欧美国产一区视频在线观看| 亚洲欧美日韩中文视频| 99riav久久精品riav| 一区二区高清在线观看| 亚洲小说欧美另类社区| 香蕉成人久久| 久久五月天婷婷| 欧美大片18| 亚洲激情av在线| 国内一区二区三区| 亚洲激情一区| 99国产精品久久久久久久| 亚洲在线第一页| 久久久久久自在自线| 亚洲国产精品久久91精品| 亚洲深夜av| 久久资源在线| 国产精品激情av在线播放| 激情综合久久| 亚洲一区二区三区欧美| 久久综合色影院| 日韩午夜精品视频| 久久久免费精品视频| 亚洲人成网在线播放| 亚洲欧美文学| 欧美美女视频| 在线观看的日韩av| 欧美永久精品| 一区二区三区国产| 久久亚洲精选| 国产精品美女主播在线观看纯欲| av成人免费| 亚洲午夜一区二区三区| 欧美成人午夜视频| 亚洲欧美在线播放| 欧美日韩亚洲综合在线| 樱花yy私人影院亚洲| 亚洲欧美日韩国产成人| 欧美激情中文字幕在线| 久久久精品国产一区二区三区| 国产精品v亚洲精品v日韩精品| 一区二区福利| 羞羞色国产精品| 99精品热视频| 久久综合中文字幕| 国内伊人久久久久久网站视频| 亚洲在线视频网站| 亚洲精品免费看| 亚洲福利国产| 另类欧美日韩国产在线| 黄色日韩网站视频| 老司机久久99久久精品播放免费| 亚洲一区二区三区免费观看| 欧美视频一区二区三区…| 亚洲伦伦在线| 亚洲精品日韩精品| 欧美日韩精品免费观看视频完整 | 久久婷婷丁香| 欧美一区激情| 国内外成人在线| 久久久一本精品99久久精品66| 亚洲欧美一区二区精品久久久| 国产精品看片你懂得| 亚洲欧美日韩一区在线观看| 一区二区三区高清不卡| 国产精品日韩在线| 久久精品国产综合| 久久久噜噜噜久久中文字幕色伊伊| 好看的av在线不卡观看| 欧美1区2区视频| 欧美国产日韩xxxxx| 亚洲最新在线视频| 亚洲深夜影院| 亚洲欧洲综合另类| 国产模特精品视频久久久久| 欧美在线播放一区二区| 久久精品国产亚洲aⅴ| 国户精品久久久久久久久久久不卡 | 一区二区免费在线播放| 国产精品乱人伦一区二区| 亚洲免费成人av电影| 亚洲日本无吗高清不卡| 亚洲精品国产精品乱码不99按摩| 欧美日韩一区二区三区在线看| 亚洲视频在线观看免费| 亚洲影音先锋| 亚洲国产欧美精品| 一区二区三区四区五区视频| 国产视频在线观看一区二区三区| 快she精品国产999| 欧美日韩中文另类| 毛片一区二区三区| 欧美日韩国产二区| 久久久久久久波多野高潮日日| 麻豆av福利av久久av| 亚洲欧美美女| 欧美国产精品久久| 久久久亚洲国产天美传媒修理工 | 亚洲国产精品第一区二区| 欧美日韩成人在线观看| 欧美电影免费观看高清| 久久国产精品久久精品国产| 欧美成人精品| 久久久久久久久一区二区| 欧美日韩小视频| 欧美成va人片在线观看| 亚洲欧美影音先锋| 一本色道久久加勒比精品| 久久se精品一区精品二区| 亚洲无线视频| 欧美激情一区二区三区在线视频| 久久成人综合视频| 欧美视频不卡中文| 亚洲激情视频网站| 午夜精品一区二区三区在线播放| 亚洲欧美日韩综合一区| 99视频一区| 榴莲视频成人在线观看| 久久久99久久精品女同性| 国产精品99一区二区| 亚洲免费av网站| 亚洲狼人综合| 女女同性女同一区二区三区91| 久久米奇亚洲| 国内久久视频| 欧美伊人久久| 久久人人爽人人爽| 国内精品久久久久伊人av| 亚洲欧美综合网| 欧美在线观看一区二区| 国产精品中文字幕在线观看| 亚洲欧美自拍偷拍| 国产精品激情| 亚洲一区二区高清视频| 亚洲激情成人网| 另类激情亚洲| 亚洲人成网站999久久久综合| 亚洲国内自拍| 久久国产精品一区二区三区| 亚洲网在线观看| 一区二区三区久久精品| 欧美成年人视频| 韩国精品一区二区三区| 一区二区精品在线| 一区二区三区国产盗摄| 一区二区欧美在线| 欧美日韩在线综合| 亚洲在线视频免费观看| 欧美一区二区三区免费在线看 | 亚洲国产日韩一区| 亚洲人成免费| 欧美日韩精品伦理作品在线免费观看| 日韩网站在线观看| 国产丝袜一区二区三区| 性亚洲最疯狂xxxx高清| 美女主播精品视频一二三四| 在线免费日韩片| 欧美日韩国产综合一区二区| 9l视频自拍蝌蚪9l视频成人| 性色av一区二区三区在线观看 | 99www免费人成精品| 欧美极品一区| 亚洲欧美国产一区二区三区| 先锋影音国产精品| 伊人男人综合视频网| 欧美成人a视频| 亚洲私人影院在线观看| 久久综合给合久久狠狠狠97色69| 亚洲人体影院| 国产农村妇女毛片精品久久麻豆| 久久精品免费观看| 99精品欧美一区二区蜜桃免费| 久久婷婷av| 亚洲欧美在线一区二区| 亚洲国产精品va在看黑人| 亚洲综合日韩中文字幕v在线| 久久综合九色九九| 亚洲综合第一页| 亚洲人成网站777色婷婷| 国产精品激情电影| 欧美经典一区二区三区| 欧美一区不卡| 99国产精品久久久| 久久偷窥视频| 亚洲人成网站在线播| 久久漫画官网| 午夜精品久久久久久久白皮肤| 亚洲国产一区二区三区在线播| 国产女精品视频网站免费| 欧美日韩精品一区二区在线播放 | 国产精品久久波多野结衣| 久久美女性网| 性欧美暴力猛交另类hd| 日韩天堂在线观看| 亚洲精品乱码久久久久| 老司机午夜精品视频| 西瓜成人精品人成网站| 亚洲视频香蕉人妖|