簡體   English   中英

如何在opengl中正確放大紋理?

[英]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_SGL_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM