紋理(知識點)
以下是紋理用到的知識點,至于具體流程操作請參考:
https://learnopengl.com/Getting-started/Textures
紋理環繞
紋理環繞(Texture Wrapping)的作用是定義在紋理坐標超出標準范圍時系統如何處理。紋理坐標通常在[0, 1]范圍內,表示紋理圖像上的相對位置。當紋理坐標超出這個范圍時,紋理包裹規定了采取的行為,以防止紋理映射時出現問題。
以下是紋理環繞的主要作用:
-
處理紋理坐標超出標準范圍: 紋理包裹確保紋理坐標在 [0, 1] 范圍內,防止超出范圍導致的問題。這包括避免紋理的重復、拉伸、擠壓或其他不自然的效果。
-
提供更自然的紋理映射: 在圖形渲染中,使用紋理包裹可以確保紋理在幾何表面上的映射看起來更加自然和符合預期。選擇適當的包裹模式有助于消除視覺上的不連續性和不規則性。
常見的紋理包裹模式包括:
-
重復(GL_REPEAT): 超出[0, 1]范圍的坐標會被截斷,將其取小數部分,使其重新回到[0, 1]范圍。適用于需要紋理在幾何圖形表面上多次重復的情況,如地板、墻壁等。
-
鏡像重復(GL_MIRRORED_REPEAT): 類似于重復,但在超出范圍時進行鏡像反轉。適用于需要紋理在重復的同時進行反轉的情況,有時可以提供更平滑的過渡。
-
夾取到邊緣(GL_CLAMP_TO_EDGE): 超出范圍的坐標會被夾取到0.0或1.0,即被強制限制在[0, 1]范圍內。適用于需要防止紋理在邊緣拉伸的情況,如繪制平鋪的地板。
-
夾取到邊緣,但在超出范圍時進行插值(GL_CLAMP_TO_BORDER): 超出范圍的坐標會被夾取到一個指定的邊界顏色。適用于需要在超出范圍時保持紋理邊緣的顏色,以模擬紋理的邊緣效果。
void glTexParameteri(GLenum target, GLenum pname, GLint param);是OpenGL中用于設置紋理參數的函數。這個函數允許你指定紋理對象的一些屬性,如紋理過濾、紋理環繞等
-
target:
參數指定了目標紋理,可以是 GL_TEXTURE_1D、GL_TEXTURE_2D、- GL_TEXTURE_3D 等。 -
pname:
參數指定了你要設置的紋理參數的名稱,比如紋理過濾參數、紋理環繞參數等。 -
param
參數指定了你要設置的參數值。
// 設置紋理過濾參數glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// 設置紋理環繞參數glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
紋理過濾
紋理過濾(Texture Filtering)是指在紋理映射到圖形對象表面時,系統如何根據紋理坐標對紋理進行采樣的過程。紋理過濾的作用是消除或減輕因紋理像素與渲染像素之間坐標不匹配而產生的鋸齒狀或失真等視覺問題。總結: 消除或減輕因紋理像素與渲染像素之間坐標不匹配而產生的鋸齒狀或失真等視覺問題
解決辦法:
紋理過濾有多種方式,其中最常見的是點過濾和線性過濾。
- 點過濾:
- 點過濾是最簡單的過濾方式,它會直接選取最接近紋理坐標的一個紋理像素的顏色。
- 適用于放大紋理,但在縮小紋理時可能產生鋸齒狀的效果。
- 線性過濾:
- 線性過濾考慮附近四個紋理像素的顏色,通過加權平均的方式進行插值。
- 在放大和縮小紋理時都相對較好地保持了圖像的平滑過渡,減少了鋸齒狀效果
總結:
在紋理縮小時使用最近鄰過濾,并在放大紋理時使用線性過濾glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
生成和加載紋理
生成紋理
// 創建紋理對象unsigned int texture;glGenTextures(1, &texture);glBindTexture(GL_TEXTURE_2D, texture);// 紋理環繞glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);// 紋理過濾glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);// 轉換數據int width, height, nrChannels;unsigned char *data = stbi_load("container.jpg", &width, &height, &nrChannels, 0);if (data){glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);glGenerateMipmap(GL_TEXTURE_2D);}else{std::cout << "Failed to load texture" << std::endl;}stbi_image_free(data);
加載紋理
其實就和 頂點數據以及顏色加載一樣。解析坐標里面的紋理坐標,復制到VBO, 然后通過glVertexAttribPointer 解析紋理屬性。利用glEnableVertexAttribArray 將數據和 頂點著色器關聯。頂點著色器的輸出作為片段著色器的輸入(FragColor = texture(ourTexture, TexCoord);)
注意點:
紋理單元: 使用一個紋理的時候,紋理單元默認是 0 , 這個時候不用刻意去設置紋理單元, 但是當紋理單元數量超過1個的時候,就要設置。 單元默認是 0 - 128 所以不同的紋理綁定不同的紋理單元
代碼鏈接地址:https://github.com/heisai/OpenglProject/tree/master/OpenglRectangleTexture