gpt4 book ai didi

opengl - 不匹配的插值

转载 作者:行者123 更新时间:2023-12-04 10:06:01 25 4
gpt4 key购买 nike

看这两张图:

enter image description here
enter image description here

两张图片上的红色和蓝色 channel 都为零,而绿色 channel 是该点的 x 坐标。 x 坐标在 (-1, 1) 范围内。

第一张图片是在 CPU 上计算出来的:

double screenHeight = 750;
double screenWidth = 750;
double viewportWidth = 2.0;

for (int i = 0; i < screenHeight; ++i) {
for (int j = 0; j < screenWidth; ++j) {
float greenChannel = (double)j / screenWidth * viewportWidth;
}
}

第二个是在 GPU 上计算的:
首先,顶点着色器被告知要绘制三个顶点(但没有给出,更多信息 here ):
layout (location = 0) out vec2 outUV;

void main() {
outUV = vec2((gl_VertexIndex << 1) & 2, gl_VertexIndex & 2);
gl_Position = vec4(vec2(outUV) * 2.0f + -1.0f, 0.0f, 1.0f);
}

这基本上将重心坐标发送到每个片段。它们是在三个值之间插入的。然后片段着色器进行了以下计算:
layout (location = 0) in vec2 outUV;
layout(location = 0) out vec4 outColor;

void main() {
double viewportWidth = 2.0;
double c = (outUv.x - 0.5) * viewportWidth;
outColor = vec4(vec3(0.0, float(c), 0.0), 1.0);
}

这首先移动 x 坐标,使其现在处于 (-0.5, -0.5) 范围内,然后缩放它以使其达到 (-1, 1) 范围。

如果您再次查看图像,您会发现它们并不相同。 CPU 在中心附近平滑得多,而在 GPU 上渲染的则过渡更突然。你知道是什么原因造成的吗?看起来可能是由于 GPU 上某处的精度损失。我认为插值的浮点数不够精确,所以我尝试了不同的 c 方法:
double screenWidth = 750;
double viewportWidth = 2.0;
double c = (gl_FragCoord.xy - 0.5 * screenWidth )/ screenWidth * viewportWidth;

这使用 gl_FragCoord 和屏幕分辨率,而不是依赖于插值。它给了我与第一次尝试无法区分的结果,所以我想这不是插值。可以肯定的是,我计算了两种方式的 c 并比较了它们。直到小数点后 7 位,它们完全相同。

有谁知道为什么这两个图像不一样?

最佳答案

GPU 图像是正确的——似乎您启用了 sRGB 处理(这很好!)。因此,您的 GPU 代码以线性方式进行插值,然后应用 sRGB Gamma 压缩函数。在 OpenGL 中,此行为由 glEnable/Disable(GL_FRAMEBUFFER_SRGB) 控制.在 Vulkan 中是 configured when creating the swapchain .

您的 CPU 代码在“错误”的色彩空间中进行插值——即通过直接计算 sRGB 值,就好像它们是线性的,即使它们不是。

您可以按如下方式修复 CPU 代码:

float greenChannel = ...;
greenChannel = greenChannel <= 0.0031308f ? 12.92f*greenChannel : 1.055f*powf(greenChannel, 1/2.4f) - 0.055f;

关于opengl - 不匹配的插值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61584384/

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