[英]How to properly upscale a texture in opengl?
讓我們說,為了這個問題的簡單性,我想創建一個包含從黑色到紅色的顏色漸變的紋理。 我知道有更簡單的方法來實現這一點,但它是我的問題的一個很好的例子。
我想,我可以簡單地從一個浮點數組創建一個紋理,如下所示:
float values[4] {
0.f, 1.f,
0.f, 1.f
}
// gen texture
unsigned int texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
// set filter and wrap
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);
// copy values
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 2, 2, 0, GL_RED, GL_FLOAT, values);
並繪制它:
float vertices[8] {
-1.f, -1.f, 0.f, 0.f,
1.f, -1.f, 1.f, 0.f,
1.f, 1.f, 1.f, 1.f,
-1.f, 1.f, 0.f, 1.f
}
// generate vertex buffer, vertex buffer layout and vertex array
unsigned int[6] indices {
0, 1, 2,
2, 3, 1
}
// generate index buffer
// bind everything
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, nullptr);
綁定頂點着色器如下所示:
#version 330 core
layout(location=0) in vec2 in_position;
layout(location=1) in vec2 in_texCoords;
out vec2 texCoords;
void main() {
gl_Position = vec4(in_position, 0.f, 1.f);
texCoords = in_texCoords;
}
片段着色器是這樣的:
#version 330 core
layout(location = 0) out vec4 out_color;
in vec2 texCoords;
uniform sampler2D u_gradient;
void main() {
float red = texture(u_gradient, texCoords).r;
out_color = vec4(red, 0.f, 0.f, 1.f);
}
在此之后,我希望在整個窗口中從左到右(黑色到紅色)獲得顏色漸變。 然而,我得到的是在 x 和 y 方向上從窗口的大約 1/4 到 3/4 的漸變(見下圖)。 我還注意到重復的換行似乎不適用於這里,因為我得到的看起來像鏡像重復。
我已經使用固定值而不是 texCoords 來處理片段着色器,並認為 x 軸上從 0.25 到 0.75 的范圍代表整個漸變(0.25 映射到 0 表示紅色,0.75 映射到 1)。
更改作為值傳遞給紋理(例如 4x4 數組)的“步驟”數量不會改變結果。
我還嘗試使用圖像作為紋理(加載了 stb_image,分辨率為 1920x1080),它工作得非常好並且可以在整個屏幕上傳播。
澄清一下:為什么梯度的 texCoords 范圍從 .25 到 .75 而不是從 0 到 1,我該如何修復它(除了調整 texCoords 本身)?
讓我們假設你有一個 2x2 的紋理
2x2 紋理
如果此紋理包裹在 6x6 片段的網格上,則紋素的中心正好位於 6x6 正方形的 3x3 瓷磚的中間的紋素上:
6x6 四邊形
其他片段的顏色取決於紋理參數 - 請參閱glTexParameter
。
由於紋理被放大, GL_TEXTURE_MAG_FILTER
很重要。
如果是GL_NEAREST
,則片段的顏色是與片段紋理坐標最接近的紋素之一:
如果是GL_LINEAR
,則通過最接近紋理坐標的 4 個像素的加權平均值對顏色進行插值。
6x6 四邊形邊界的插值取決於包裹參數GL_TEXTURE_WRAP_S
和GL_TEXTURE_WRAP_T
。
如果參數為GL_REPEAT
(默認值),則紋理將被視為無限紋理,並且邊界處顏色插值的插值會考慮紋理另一側的紋素。 這用於無縫紋理和平鋪:
如果是GL_CLAMP_TO_EDGE
,則邊界處的內插顏色將被限制為紋理邊界處紋素的顏色:
將紋理包裹參數GL_CLAMP_TO_EDGE
應用於紋理對象,
float values[4] { 0.f, 1.f, 0.f, 1.f };
unsigned int texId;
glGenTextures(1, &texId);
glBindTexture(GL_TEXTURE_2D, texId);
// set filter and wrap
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_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
// copy values
glTexImage2D(GL_TEXTURE_2D, 0, GL_R32F, 2, 2, 0, GL_RED, GL_FLOAT, values);
得到以下梯度:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.