gpt4 book ai didi

opengl - 为什么我的 OpenGL 纹理渲染变暗了? (RGB值是平方的)

转载 作者:行者123 更新时间:2023-12-02 17:59:33 27 4
gpt4 key购买 nike

我一直在使用glow 在 Rust 中进行一些 opengl 渲染。进展顺利,但是渲染到纹理与渲染到图像给了我不同的结果。我知道一个简单的解决方法,但我只是不明白。

enter image description here

右侧的图像直接渲染到屏幕上,而左下角的图像是通过使用相同的绘制函数将相同的网格渲染到相同大小的纹理(将像素数据传递到 egui 的 ColorImage)来创建的。正如你所看到的,它太暗了,当我将像素数据保存到文件中时也是如此(使用 Rust 的 Image crate)。

但是,如果渲染中 channel 的值已满,则输出中的 channel 值也已满,就像在转换为 RGB8 之前将 RGB 值在 0-1.0 范围内进行平方一样。果然,我尝试在像素数据中撤消该操作 (flipped_buffer[i1] = ((buffer[i2] as f32/255.).sqrt() * 255.).round() as u8;),它开始看起来是正确的!

那么为什么?这是一个非常具体的事情,我什至可以想象它是一种映射颜色的有用方法(因为眼睛比亮值更好地区分较暗的值),但为什么会发生在这里?

写入纹理的代码基于教程 here ,但使用 Rust 中的发光而不是 C/C++,并使用 RGBA 而不是 RGB。

纹理创建摘录:

let gl_texture = self.gl.create_texture()?;
self.gl.bind_texture(glow::TEXTURE_2D, Some(gl_texture));
self.gl.tex_image_2d(glow::TEXTURE_2D, 0, glow::RGBA as i32, width as i32, height as i32, 0, glow::RGBA, glow::UNSIGNED_BYTE, None);
self.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MAG_FILTER, glow::NEAREST as i32);
self.gl.tex_parameter_i32(glow::TEXTURE_2D, glow::TEXTURE_MIN_FILTER, glow::NEAREST as i32);

像素数据读取摘录:

let mut buffer = vec![0 as u8; (width * height * 4) as usize];
self.gl.get_tex_image(
glow::TEXTURE_2D,
0,
glow::RGBA,
glow::UNSIGNED_BYTE,
glow::PixelPackData::Slice(buffer.as_mut_slice()));

最佳答案

您似乎在某处启用了GL_FRAMEBUFFER_SRGB。这样做的效果是,当您渲染到屏幕时,来自着色器的线性值将使用 sRGB transfer function 进行 Gamma 压缩。 (这不完全是平方根,但你明白了)。当渲染到非 sRGB 纹理时,根本不会发生转换,因为几乎所有 8 位文件格式和 API 都假定 8 位数据已经在 sRGB 色彩空间中。因此,当您将其保存到文件并使用期望其为 sRGB 的查看器打开它时,它看起来会更暗。该“egui”库似乎也需要 sRGB 图像。

解决方案是将内部纹理格式更改为 GL_SRGB8_ALPHA8:

self.gl.tex_image_2d(glow::TEXTURE_2D, 0, glow::SRGB8_ALPHA8 as i32, width as i32, height as i32, 0, glow::RGBA, glow::UNSIGNED_BYTE, None);

关于opengl - 为什么我的 OpenGL 纹理渲染变暗了? (RGB值是平方的),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/74775344/

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