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); }
关键注意事项
- ES3.0不支持桌面OpenGL中
GL_RGB内部格式搭配GL_RED格式的松散匹配,必须保证内部格式与格式的分量数一致。 - 若设备老旧导致GL_R16UI/GL_R16支持异常,可通过
glGetInternalformativ查询设备是否支持对应格式。 - 确认你的16位数据移位正确:比如YUV420P10le的10位数据左移6位后,需保证是无符号16位类型,无溢出。
内容的提问来源于stack exchange,提问作者zuguorui
相关产品推荐
相关产品推荐

