让我们说,为了简单起见,我想创建一个包含从黑色到红色的颜色渐变的纹理。我知道实现这一目标的方法要简单得多,但这是解决我的问题的一个很好的例子。
我想,我可以像这样简单地从float数组创建纹理:
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轴上从.25到.75的范围代表整个渐变(.25映射到0代表红色,0.75代表1 )。
更改作为值传递给纹理(例如4x4数组)的“步数”并不会改变结果。
我还尝试过使用图像作为纹理(加载了stb_image,分辨率为1920x1080),其效果非常好,并且可以在整个屏幕上散布。
为澄清起见:为什么渐变的texCoords范围从.25到.75而不是从0到1,我该如何解决(除了调整texCoords本身)?
答案 0 :(得分:6)
假设您具有2x2纹理
2x2纹理
如果此纹理包裹在6x6片段的网格上,则纹理像素的中心正好位于6x6正方形3x3瓷砖中间的纹理像素上:
6x6 quad
其他片段的颜色取决于纹理参数-请参见glTexParameter
。
由于纹理被放大,因此mouseleave
很重要。
如果它是GL_TEXTURE_MAG_FILTER
,则片段的颜色是最接近片段纹理坐标的texel之一:
如果它是GL_NEAREST
,则通过最接近纹理坐标的4个像素的加权平均值对颜色进行插值。
6x6四边形边界处的插值取决于换行参数GL_LINEAR
和GL_TEXTURE_WRAP_S
。
如果参数为GL_TEXTURE_WRAP_T
(默认设置),则将纹理视为无休止的纹理,并且在边界处对颜色插值进行插值时要考虑到其相对侧的纹素。质地。这用于无缝纹理和平铺:
如果它是GL_REPEAT
,则边界处的插值颜色将被钳制为纹理边界处的纹素的颜色:
将纹理包裹参数GL_CLAMP_TO_EDGE
应用于纹理对象
GL_CLAMP_TO_EDGE
获得以下渐变: