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

WisKeyのLullaby

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

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

公告

“我該走哪條路?”
“這取決于你要去哪里。”
“我只想能到某個(gè)地方。”
“只要你走的夠遠(yuǎn),你始終能到達(dá)那個(gè)地方。”

Home: huangwei.pro
E-Mail: sir.huangwei [at] gmail.com
09.6 畢業(yè)于杭州電子科技大學(xué)
進(jìn)入網(wǎng)易杭州研究院工作至今

常用鏈接

留言簿(1)

我參與的團(tuán)隊(duì)

搜索

  •  

積分與排名

  • 積分 - 51837
  • 排名 - 449

最新評(píng)論

閱讀排行榜

評(píng)論排行榜

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

 

在本文中,我們將給三角形加一個(gè)貼圖,這需要在頂點(diǎn)和片段著色器中加入一些新變量,創(chuàng)建和使用貼圖對(duì)象,并且學(xué)習(xí)一點(diǎn)貼圖單元和貼圖坐標(biāo)的知識(shí)。

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

獲取代碼

所有例子代碼的zip打包可以從這里獲取:https://github.com/tomdalling/opengl-series/archive/master.zip

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

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

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

著色器變量Uniform與Attribute

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

著色器變量有兩種類型:uniformattributeattribute變量可以在每個(gè)頂點(diǎn)上有不同值。而uniform變量在多個(gè)頂點(diǎn)上保持相同值。比如,你想要給一個(gè)三角形設(shè)置一種顏色,那你應(yīng)該使用uniform變量,如果你希望每個(gè)三角形頂點(diǎn)有不同顏色,你應(yīng)該使用attribute變量。從這開始,我稱呼他們?yōu)?#8220;uniforms”和“attributes”。

Uniforms能被任意著色器訪問,但是Attributes必須先進(jìn)入頂點(diǎn)著色器,而非片段著色器。頂點(diǎn)著色器在需要時(shí)會(huì)將該值傳給片段著色器。這因?yàn)閁niforms像常量-它們不會(huì)被任何著色器更改。然而,Attributes不是常量。頂點(diǎn)著色器會(huì)改變Attribute變量的值,在片段著色器獲取之前。就是說,頂點(diǎn)著色器的輸出就是片段著色器的輸入。

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

貼圖

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

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

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

hazard.png

 

我們使用tdogl:Bitmap來加載“hazard.png”的原始像素?cái)?shù)據(jù)到內(nèi)存中,參見stb_image幫助文檔。然后我們使用tdogl:Texture上傳原始像素?cái)?shù)據(jù)給OpenGL貼圖對(duì)象。幸運(yùn)的是OpenGL中的貼圖創(chuàng)建方法從面世到現(xiàn)在都沒有實(shí)質(zhì)性的變化,所以網(wǎng)上有大量的創(chuàng)建貼圖的好文章。雖然貼圖坐標(biāo)的傳輸方式有變化,但創(chuàng)建貼圖還是跟以前一樣。

以下是tdogl:Texture的構(gòu)造函數(shù),用于OpenGL貼圖創(chuàng)建。

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); } 

貼圖坐標(biāo)

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

uv_coords.png

 

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

貼圖圖像單元

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

對(duì)于貼圖單元是有數(shù)量限制的。在低端硬件上,如手機(jī),它們只有兩個(gè)貼圖單元。既然如此,即使我們有許多的貼圖,我們也只能同時(shí)使用兩個(gè)貼圖單元在著色器中。我們?cè)诒疚闹兄挥玫搅艘粋€(gè)貼圖,所以也只需要一個(gè)貼圖單元,但它可以在多個(gè)不同的著色器中混合。

實(shí)現(xiàn)貼圖

首先,讓我們創(chuàng)建一個(gè)新的全局貼圖。

tdogl::Texture* gTexture = NULL; 

我們?yōu)榧虞d“hazard.png”圖片新增一個(gè)函數(shù)。該函數(shù)能被AppMain所調(diào)用。

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

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

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, }; 

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

#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關(guān)鍵字說明texuniform變量。貼圖是一致的,因?yàn)樗腥切雾旤c(diǎn)有相同的貼圖。sampler2D是變量類型,說明它包含一個(gè)2D貼圖。

fragTexCoordattribute變量,因?yàn)槊總€(gè)三角形頂點(diǎn)是不同的貼圖坐標(biāo)。

texture函數(shù)是用來查找給定貼圖坐標(biāo)的像素顏色。在GLSL舊版本中,你應(yīng)該使用texture2D函數(shù)來實(shí)現(xiàn)該功能。

我們無法直接傳送attribute給判斷著色器,因?yàn)?em style="box-sizing: border-box;">attribute必須首先通過頂點(diǎn)著色器。這兒是修改過的頂點(diǎn)著色器:

#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); } 

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

著色器有兩個(gè)變量需要我們?cè)O(shè)置:vertTexCoordattribute變量和texuniform變量。讓我們從設(shè)置tex變量開始。打開main.cpp,找到Render()函數(shù)。我們?cè)诶L制三角形之前設(shè)置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 

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

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

然后我們?cè)O(shè)置貼圖單元索引給texuniform著色器變量。我們使用0號(hào)貼圖單元,所以我們?cè)O(shè)置tex變量為整數(shù)0setUniform方法只是調(diào)用了glUnifrom1i函數(shù)。

最后一步,獲取貼圖坐標(biāo)給vertTexCoordattribute變量。為了實(shí)現(xiàn)它,我們需要修改LoadTriangle()函數(shù)中的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); 

現(xiàn)在我們需要改成這樣:

// 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))); 

我們第二次調(diào)用了glVertexAttribPointer,但我們也修改了第一個(gè)調(diào)用。最重要的是最后兩個(gè)參數(shù)。

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

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

現(xiàn)在,當(dāng)你運(yùn)行程序,你就能看到如本文最上方的那個(gè)三角形。

下篇預(yù)告

下一篇教程中我們會(huì)學(xué)一些矩陣相關(guān)的東西,使用矩陣來旋轉(zhuǎn)立方體,移動(dòng)相機(jī),和添加透視投影。我們還會(huì)學(xué)習(xí)深度緩沖和基于時(shí)間更新的邏輯,比如動(dòng)畫。

更多OpenGL貼圖相關(guān)資源

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

Feedback

# re: 現(xiàn)代OpenGL教程 02 - 貼圖 2015-12-01 17:13 mmocake
給三角形加一個(gè)貼圖,學(xué)習(xí)了,MARK下  回復(fù)  更多評(píng)論
  


只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            夜色激情一区二区| 在线一区二区日韩| 欧美成ee人免费视频| 亚洲一区二区三区国产| 欧美在线视频a| 亚洲大胆人体在线| 国产精品美女黄网| 国产精品高清免费在线观看| 欧美黄色免费| 欧美天天影院| 国产精品免费区二区三区观看| 麻豆成人在线播放| 欧美风情在线观看| 国产精品国产成人国产三级| 国产精品久久久一区二区| 国产精品一区二区久久| 国产日韩欧美视频在线| 黄色精品一区二区| 亚洲美洲欧洲综合国产一区| 亚洲一区日本| 欧美激情精品久久久久久蜜臀 | 亚洲欧美日韩成人高清在线一区| 亚洲一区二区成人| 美女视频网站黄色亚洲| 欧美系列一区| 亚洲国产欧美一区二区三区同亚洲| 亚洲国产精品一区二区三区 | 麻豆精品在线视频| 国产精品一区免费视频| 亚洲人www| 美女国内精品自产拍在线播放| 欧美日韩国产精品一卡| 国产视频欧美| 国产精品永久入口久久久| 亚洲国产精品悠悠久久琪琪| 性做久久久久久| 在线视频你懂得一区| 欧美大片在线影院| 亚洲国产婷婷| 欧美激情一区二区三区| 久久久久久九九九九| 国内外成人免费激情在线视频 | 国产视频欧美| 久久av红桃一区二区小说| 亚洲一区二区三区视频播放| 欧美亚洲不卡| 久久婷婷一区| 免费观看在线综合色| 亚洲激情欧美| 一区二区三区四区五区视频| 欧美另类专区| 亚洲婷婷综合色高清在线| 亚洲一区免费视频| 国内一区二区三区在线视频| 久久久久在线| 欧美日韩成人一区| 极品尤物久久久av免费看| 亚洲特级片在线| 亚洲一区二区三区色| 亚洲激情电影在线| 在线视频欧美日韩| 国产专区欧美精品| 亚洲精品久久久久久久久| 国产精品私房写真福利视频| 久久久久国产免费免费| 欧美日韩国产综合视频在线观看中文 | 久久久777| 欧美日韩国产bt| 久久网站免费| 国产亚洲午夜| 亚洲欧美在线视频观看| 亚洲免费黄色| 欧美日韩大片| 亚洲国产日韩一区二区| 亚洲高清视频一区二区| 亚洲欧美偷拍卡通变态| 亚洲性av在线| 国产精品一卡| 欧美一级黄色录像| 久久精品国产99| 国产欧美欧美| 久久久不卡网国产精品一区| 久久精品国产第一区二区三区| 欧美视频在线观看视频极品| 99国产精品视频免费观看一公开| 亚洲国产一区二区三区a毛片| 久久综合久久综合久久综合| 久久综合九色综合久99| 最新国产の精品合集bt伙计| 欧美96在线丨欧| 99国产精品私拍| 久久九九99| 亚洲精品一区在线| 国产精品入口麻豆原神| 久久精品99久久香蕉国产色戒| 欧美18av| 国产精品美女主播| 亚洲欧美卡通另类91av| 欧美 日韩 国产 一区| 亚洲婷婷综合色高清在线| 国产精品永久免费在线| 欧美黄色小视频| 久久精品国产精品 | 欧美成人中文字幕| 亚洲激情在线播放| 国产视频一区在线观看| 欧美精品v日韩精品v国产精品| 亚洲女女女同性video| 最新日韩精品| 欧美激情一区二区三区成人| 久久精品视频导航| 欧美一区二区三区在线观看 | 欧美va天堂在线| 国产精品亚洲综合一区在线观看| 久久久中精品2020中文| 亚洲欧美激情视频在线观看一区二区三区| 久久美女性网| 久久久久99精品国产片| 亚洲欧美日韩视频二区| 亚洲少妇自拍| 亚洲欧美视频在线| 欧美一区观看| 久久综合精品国产一区二区三区| 久久精品在这里| 麻豆成人精品| 亚洲茄子视频| 中日韩视频在线观看| 亚洲天堂男人| 久久免费视频一区| 欧美日韩另类一区| 国产九色精品成人porny| 国产亚洲欧美另类中文| 在线一区二区三区四区五区| 99在线视频精品| 欧美亚洲色图校园春色| 久久久亚洲成人| 欧美日韩一区二区国产| 狠狠爱综合网| 亚洲欧美久久久久一区二区三区| 欧美在线观看网站| 欧美福利一区| 欧美一区二区性| 国产精品国产三级国产专播品爱网| 国产亚洲精品久久久| 日韩亚洲精品电影| 久久婷婷国产麻豆91天堂| 一区二区三区福利| 欧美福利一区二区| 国产一区二区三区久久| 国产精品99久久久久久久久久久久 | 黄色成人在线观看| 性色av一区二区三区红粉影视| 亚洲国产成人精品女人久久久 | 一区二区精品国产| 久久亚洲私人国产精品va| 国产精品高潮呻吟久久| 在线综合亚洲| 在线性视频日韩欧美| 欧美视频中文在线看 | 国产精品乱码一区二三区小蝌蚪 | 久久亚洲综合网| 欧美诱惑福利视频| 国产九色精品成人porny| 欧美主播一区二区三区| 欧美在线高清| 亚洲日产国产精品| 99精品久久免费看蜜臀剧情介绍| 欧美日韩视频在线观看一区二区三区 | 夜夜嗨av一区二区三区四季av| 久久一区二区三区四区五区| 久久成人人人人精品欧| 影音先锋中文字幕一区二区| 免费一区二区三区| 欧美日本久久| 久久精品视频在线看| 久热精品视频在线免费观看| 一区二区三区欧美激情| 亚洲欧美日韩天堂| 亚洲精品国产精品国产自| 亚洲一本视频| 亚洲人久久久| 久久精品国产综合| 午夜亚洲福利在线老司机| 免费久久久一本精品久久区| 午夜欧美大尺度福利影院在线看| 免费不卡在线视频| 久久野战av| 国产精品色午夜在线观看| 亚洲国产成人午夜在线一区| 国产日韩高清一区二区三区在线| 亚洲国产精品久久久久秋霞影院 | 欧美午夜精品久久久久久浪潮| 欧美一区二区私人影院日本| 欧美区一区二| 亚洲激情一区二区| 91久久久久久久久| 欧美成年人网| 亚洲欧洲在线视频| 亚洲一区二区三区精品动漫| 亚洲国产天堂久久综合网|