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

Android平台OpenGL ES3.0创建单分量16位深度纹理失败求助

Android OpenGL ES3.0 创建16位单分量纹理的正确方案

针对你遇到的GL_INVALID_OPERATION错误,核心原因是整数纹理不支持线性过滤,同时ES3.0与桌面OpenGL的格式匹配规则存在差异。以下提供两种可行方案:

方案一:无符号整数纹理(GL_R16UI)

适合需要保留原始16位整数数据的场景,需注意纹理过滤规则和着色器采样方式:

代码实现

GLenum glError;
GLuint tex_y;
glGenTextures(1, &tex_y);
glBindTexture(GL_TEXTURE_2D, tex_y);

// 整数纹理仅支持GL_NEAREST过滤,不能用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);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);

// ES3.0要求整数纹理的格式组合严格匹配:内部格式GL_R16UI,格式GL_RED_INTEGER,类型GL_UNSIGNED_SHORT
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16UI, y_width, y_height, 0, GL_RED_INTEGER, GL_UNSIGNED_SHORT, pix_y);

// 若设备兼容性问题导致mipmap生成报错,可暂时注释该行
glGenerateMipmap(GL_TEXTURE_2D);

glError = glGetError();
if (glError != GL_NO_ERROR) {
    LOGE(TAG, "y, glError: 0x%x", glError);
}

对应片段着色器

需使用usampler2D类型采样整数纹理,手动转换为浮点值:

#version 300 es
precision mediump float;
uniform usampler2D tex_y; // 注意是usampler2D,而非普通sampler2D
in vec2 v_texCoord;
out vec4 fragColor;

void main() {
    uint y_raw = texture(tex_y, v_texCoord).r;
    // 将16位整数归一化到[0.0, 1.0],适配你左移6位的10位数据
    float y = float(y_raw) / 65535.0;
    // 后续YUV转RGB逻辑
    fragColor = vec4(y, y, y, 1.0);
}

方案二:归一化16位纹理(GL_R16)

更接近你原8位GL_LUMINANCE的使用习惯,支持线性过滤,无需修改太多原有逻辑:

代码实现

GLenum glError;
GLuint tex_y;
glGenTextures(1, &tex_y);
glBindTexture(GL_TEXTURE_2D, tex_y);

// 可继续使用GL_LINEAR过滤,与原8位逻辑一致
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

// 归一化纹理格式组合:内部格式GL_R16,格式GL_RED,类型GL_UNSIGNED_SHORT
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, y_width, y_height, 0, GL_RED, GL_UNSIGNED_SHORT, pix_y);

glGenerateMipmap(GL_TEXTURE_2D);

glError = glGetError();
if (glError != GL_NO_ERROR) {
    LOGE(TAG, "y, glError: 0x%x", glError);
}

对应片段着色器

与原8位逻辑完全兼容,直接采样得到归一化浮点值:

#version 300 es
precision mediump float;
uniform sampler2D tex_y;
in vec2 v_texCoord;
out vec4 fragColor;

void main() {
    float y = texture(tex_y, v_texCoord).r; // 直接获取[0.0, 1.0]的归一化值
    // 后续YUV转RGB逻辑
    fragColor = vec4(y, y, y, 1.0);
}

关键注意事项

  1. ES3.0不支持桌面OpenGL中GL_RGB内部格式搭配GL_RED格式的松散匹配,必须保证内部格式与格式的分量数一致。
  2. 若设备老旧导致GL_R16UI/GL_R16支持异常,可通过glGetInternalformativ查询设备是否支持对应格式。
  3. 确认你的16位数据移位正确:比如YUV420P10le的10位数据左移6位后,需保证是无符号16位类型,无溢出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 04:05:25