gpt4 book ai didi

c++ - 如何在 opengl 中正确升级纹理?

转载 作者:行者123 更新时间:2023-11-30 00:43:31 26 4
gpt4 key购买 nike

假设,为了这个问题的简单性,我想创建一个纹理,其中包含从黑色到红色的颜色渐变。我知道有更简单的方法可以实现这一点,但它是我的问题的一个很好的例子。

我想,我可以像这样简单地从 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);

绑定(bind)的顶点着色器看起来像这样:

#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 的范围代表整个渐变(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);

得到如下渐变:

关于c++ - 如何在 opengl 中正确升级纹理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53974343/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com