You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenGL glTexSubImage2D写入像素渲染异常问题

问题描述

我有一组存储字母q像素数据的无符号字节数组,需要调用glTexImage2D写入OpenGL纹理。代码中已经做了两层有效性校验:一是确认宽度、高度的乘积和数组长度完全匹配,二是把像素打印到终端做可视化验证。代码基于Rust编写,GL调用逻辑和其他语言的绑定规则完全一致:

// create the array of pixels
let data: &[u8] = &[
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, 37, 2, 0, 0, 0, 0, 0, 0, 0, 119,
    248, 252, 241, 92, 223, 130, 0, 0, 0, 84, 253, 108, 8, 36, 202, 248, 130, 0, 0, 0,
    198, 182, 0, 0, 0, 52, 255, 130, 0, 0, 0, 241, 120, 0, 0, 0, 0, 245, 130, 0, 0, 3,
    252, 108, 0, 0, 0, 0, 233, 130, 0, 0, 0, 223, 143, 0, 0, 0, 14, 253, 130, 0, 0, 0,
    144, 234, 20, 0, 0, 126, 255, 130, 0, 0, 0, 23, 219, 223, 142, 173, 194, 231, 130,
    0, 0, 0, 0, 18, 120, 156, 108, 13, 223, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 130,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 223, 130, 0, 0, 0, 0, 0, 0, 0, 0, 0, 149, 87, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0,
];

// check that WxH equals the number of pixels
let data_w = 11;
let data_h = 15;
assert_eq!(data_w * data_h, data.len());

// write the pixels to the texture
glBindTexture(GL_TEXTURE_2D, texture);

// initialize the texture
glTexImage2D(
    GL_TEXTURE_2D,
    0,
    GL_RED as _,
    256,
    256,
    0,
    GL_RED,
    GL_UNSIGNED_BYTE,
    ptr::null(),
);

// write the pixels
glTexSubImage2D(
    GL_TEXTURE_2D,
    0,
    0,
    0,
    data_w as _,
    data_h as _,
    GL_RED,
    GL_UNSIGNED_BYTE,
    data.as_ptr() as _,
);

// print the pixels to the terminal
let mut counter = 0;
for _ in 0..data_h {
    for _ in 0..data_w {
        if data[counter] > 100 {
            print!("+");
        } else {
            print!(" ");
        }
        counter += 1;
    }
    println!()
}

终端打印的像素可视化结果如下,可以正确显示字母q的轮廓,证明像素数据本身没有问题:

++++ ++
   ++  +++
  ++    ++
  ++    ++
  ++    ++
  ++    ++
  ++   +++
   +++++++
    +++ ++
        ++
        ++
        +

但纹理渲染到屏幕时出现了扭曲错位,实际效果如下:
扭曲错位的q纹理渲染结果

故障原因

OpenGL对传入的像素数据有默认的行对齐要求:GL_UNPACK_ALIGNMENT参数默认值为4,即要求每一行像素的起始内存地址是4的倍数,每行数据长度不足4的倍数时会自动在末尾补位跳过字节。
当前传入的像素格式是GL_RED+GL_UNSIGNED_BYTE,每个像素占1字节,每行共11个像素也就是11字节,不是4的倍数。OpenGL读取像素时会按每行12字节(补1个空字节对齐)解析,导致从第二行开始所有像素的读取位置全部偏移,最终渲染结果扭曲错位。

解决方法

在调用glTexSubImage2D(或glTexImage2D)上传像素数据之前,添加一行代码将像素解包的行对齐设置为1字节(即紧密排列,不做对齐补位)即可:

// C/C++ 写法
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Rust 写法
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 1);

设置后OpenGL会按实际的每行11字节长度解析像素,不会再出现错位问题。


内容的提问来源于stack exchange,提问作者Roy Varon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 08:12:23