紋理
我們使用紋理為圖形增加更多的細(xì)節(jié)。
紋理坐標(biāo)在x和y軸上,范圍為0到1之間。使用紋理坐標(biāo)獲取紋理顏色叫做采樣(Sampling)。紋理坐標(biāo)始于(0, 0),也就是紋理圖片的左下角,終于(1, 1),即紋理圖片的右上角。
創(chuàng)建紋理
創(chuàng)建紋理和之前創(chuàng)建OpenGL對(duì)象的方式一樣。

GL_TEXTURE_2D是我們使用的紋理類型。
紋理環(huán)繞方式
創(chuàng)建紋理后,我們需要設(shè)置紋理環(huán)繞方式。紋理環(huán)繞方式用來(lái)控制紋理在物體表面上的重復(fù)、拉伸或鏡像效果。以下是常見(jiàn)的紋理環(huán)繞方式:
GL_REPEAT(默認(rèn)):紋理在物體表面上重復(fù)平鋪。
GL_MIRRORED_REPEAT:和GL_REPEAT一樣,但在每次重復(fù)時(shí),紋理會(huì)進(jìn)行鏡像翻轉(zhuǎn)。
GL_CLAMP_TO_EDGE:紋理坐標(biāo)會(huì)被約束在0到1之間,超出的部分會(huì)重復(fù)紋理坐標(biāo)的邊緣,產(chǎn)生一種邊緣被拉伸的效果。
GL_CLAMP_TO_BORDER:超出范圍的紋理坐標(biāo)會(huì)使用指定的邊界顏色來(lái)采樣。
我們一般使用函數(shù)glTexParameteri()設(shè)置紋理環(huán)繞方式。

第一個(gè)參數(shù)指定了紋理類型,譬如我們使用的是2D紋理,為GL_TEXTURE_2D。第二個(gè)參數(shù)為設(shè)置的選項(xiàng)。第三個(gè)參數(shù)是紋理環(huán)繞方式。
下面設(shè)置了水平方向和垂直方向的環(huán)繞方式:

GL_TEXTURE_WRAP_S和GL_TEXTURE_WRAP_T分別代表紋理坐標(biāo)的水平和垂直方向。
加載紋理
我們使用stb_image庫(kù)來(lái)加載圖像。
函數(shù)stbi_load()可以將圖片加載到內(nèi)存中:

filename是要加載的圖像文件的文件名。
width是一個(gè)指向整數(shù)的指針,用于存儲(chǔ)圖像的寬度。
height用于存儲(chǔ)圖像的高度。
channels用于存儲(chǔ)圖像的通道數(shù)。
desired_channels是期望的輸出通道數(shù),通??梢栽O(shè)置為0來(lái)保持原始圖像通道數(shù)。
注意,由于OpenGL要求y軸0坐標(biāo)在圖片的底部,但是通常圖片的y軸的0坐標(biāo)通常在頂部。因此我們加載的紋理是上下顛倒的。我們需要在加載紋理之前調(diào)用翻轉(zhuǎn)y軸的函數(shù):

生成紋理
現(xiàn)在我們使用之前創(chuàng)建的紋理對(duì)象和加載進(jìn)來(lái)的圖片生成一個(gè)紋理。
調(diào)用函數(shù)glTexImage2D()。

target: 紋理目標(biāo),通常為GL_TEXTURE_2D。
level: 紋理級(jí)別,通常為0,表示基本級(jí)別。
internalFormat: 指定紋理的內(nèi)部格式,比如GL_RGB。
width: 紋理的寬度。
height: 紋理的高度。
border: 邊框的寬度,通常為0。
format: 傳入數(shù)據(jù)的格式,比如GL_RGB。
type: 傳入數(shù)據(jù)的數(shù)據(jù)類型。
data: 指向圖像數(shù)據(jù)的指針。
接下來(lái)我們還需要調(diào)用glGenerateMipmap(GL_TEXTURE_2D)。這個(gè)函數(shù)的作用我們暫且忽略,之后會(huì)提及。
生成紋理后,還應(yīng)及時(shí)釋放圖像的內(nèi)存。

下面是生成一個(gè)紋理的基本流程:

應(yīng)用紋理
首先更新頂點(diǎn)數(shù)據(jù),增加紋理坐標(biāo)。

接著配置頂點(diǎn)屬性。之后我們要更新著色器代碼。
頂點(diǎn)著色器:我們把紋理坐標(biāo)發(fā)送到頂點(diǎn)著色器中,再?gòu)捻旤c(diǎn)著色器發(fā)送到片段著色器。

片段著色器:現(xiàn)在片段著色器最終輸出的顏色應(yīng)是對(duì)紋理采樣得到的顏色。
函數(shù)texture()在GLSL中用于從紋理中采樣顏色值。

sampler是一個(gè)二維紋理采樣器類型,用于指定從哪個(gè)紋理單元中進(jìn)行采樣。可以將紋理單元視為存儲(chǔ)紋理圖像的位置。coordinates是一個(gè)二維向量,表示從紋理中采樣的坐標(biāo)。texture()會(huì)根據(jù)指定的紋理采樣器和坐標(biāo),在紋理圖像上找到對(duì)應(yīng)位置的顏色值,并返回一個(gè)vec4類型的顏色值。所以我們要在片段著色器中聲明一個(gè)采樣器變量sampler。

雖然sampler是一個(gè)uniform全局變量,但我們并不需要對(duì)其賦值。原因之后會(huì)提及。
到此我們已經(jīng)可以成功把一個(gè)紋理應(yīng)用在圖形上了:

在片段著色器中,我們還可以把紋理和顏色進(jìn)行混合,只需把二者相乘:

這是混合后的效果:
