OpenGL如何将1D缓存生成2D纹理并加载?代码渲染异常如何解决?
核心问题1:像素缓冲区索引计算错误
RGBA格式下每个像素占4字节,每行1152像素的总字节数为BUFF_WIDTH * 4,你当前的索引计算逻辑完全不符合内存布局:
- 第一个版本中
int32_t ind = y * BUFF_WIDTH + x * 4的写法,相当于每一行仅偏移了1152字节,而实际一行有1152*4=4608字节,导致大部分像素数据都写到了缓冲区前1/4的位置,后续内存都是未初始化的脏数据,自然渲染出来的有效内容尺寸极小,还会重复采样脏数据。 - 第二个排查版本中
x=x+4+ind = y*BUFF_WIDTH +x的逻辑更是完全错误,相当于每4个像素才写1个像素的颜色,其余都是脏数据。
正确的索引计算应为:int32_t ind = y * BUFF_WIDTH * 4 + x * 4;
核心问题2:glTexImage2D参数传参顺序错误
glTexImage2D的参数顺序是先宽后高,你当前写的:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, BUFF_HEIGHT, BUFF_WIDTH, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
将宽高顺序传反,虽然你当前宽高都是1152暂时没触发问题,但后续宽高不一致时会直接导致图像拉伸变形。正确写法应为:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, BUFF_WIDTH, BUFF_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);
核心问题3:纹理过滤参数未正确配置
OpenGL默认的纹理缩小过滤参数是GL_NEAREST_MIPMAP_LINEAR,需要生成完整的mipmap链才能正常采样。如果你没有生成mipmap,需要手动将过滤参数改为非mipmap模式,否则纹理采样会失败,出现黑屏或异常渲染结果。在绑定纹理后添加以下代码即可:
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
其他小问题
你用new[]分配的数组,释放时应该用delete[] buffer而非delete buffer,否则会出现内存泄漏。
修正后的最简可运行代码
void OpenGLRenderer::renderScreenAlignedQuad(const XrCompositionLayerProjectionView& view) { CHECK_GL_ERROR(glBindVertexArray(m_screenAlignedQuad.vao)); CHECK_GL_ERROR(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_screenAlignedQuad.indexBuffer)); // Update texture glPixelStorei(GL_UNPACK_ALIGNMENT, 4); glBindTexture(GL_TEXTURE_2D, m_screenAlignedQuad.texture); // 配置纹理参数 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); #define BUFF_HEIGHT 1152 #define BUFF_WIDTH 1152 unsigned char *buffer = new unsigned char[BUFF_HEIGHT * BUFF_WIDTH * 4]; for (int32_t y = 0; y < BUFF_HEIGHT; y++) { for (int32_t x = 0; x < BUFF_WIDTH; x++) { // 修正索引计算 int32_t ind = y * BUFF_WIDTH * 4 + x * 4; buffer[ind] = 255; // R buffer[ind + 1] = 0; // G buffer[ind + 2] = 0; // B buffer[ind + 3] = 255; // A } } {// =! Critical section != std::shared_lock<std::shared_mutex> sl(m_videoStreamContext.g_currentFrameDataMutex); // 修正宽高传参顺序 CHECK_GL_ERROR(glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, BUFF_WIDTH, BUFF_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer)); }// =! Critical section != delete[] buffer; // 修正数组释放方式 CHECK_GL_ERROR(glDrawElements(GL_TRIANGLES, m_screenAlignedQuad.indexCount, GL_UNSIGNED_SHORT, 0)); }
内容的提问来源于stack exchange,提问作者Mateusz Sadowski
相关产品推荐
相关产品推荐

