You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

OpenGL 4.1环境下glClearTexImage()的替代实现方案咨询

OpenGL 4.1环境下glClearTexImage()的替代实现方案咨询

嘿,刚好遇到过类似的场景,在OpenGL 4.1下要清除R32I类型的颜色附件,确实没法用4.4才引入的glClearTexImage(),给你两个靠谱的替代方案,根据你的使用场景选就行:

方案一:用全屏着色器渲染清除(推荐频繁清除的场景)

这个方法不需要CPU内存开销,直接在GPU端完成清除,适合需要反复清除缓冲区的情况:

  1. 准备极简的全屏着色器
    顶点着色器不需要任何输入属性,直接通过gl_VertexID生成全屏覆盖的顶点:

    #version 150 // 对应OpenGL 3.2,4.1完全兼容
    void main() {
        // 生成覆盖整个屏幕的三角形顶点
        vec2 pos = vec2(gl_VertexID % 2, gl_VertexID / 2) * 2.0 - 1.0;
        gl_Position = vec4(pos, 0.0, 1.0);
    }
    

    片段着色器直接输出你需要的清除值-1到目标颜色附件:

    #version 150
    layout(location = 1) out int color2;
    void main() {
        color2 = -1;
    }
    
  2. 执行清除操作
    绑定你的帧缓冲区,设置好视口,然后绘制全屏三角形即可:

    // 绑定目标帧缓冲区
    glBindFramebuffer(GL_FRAMEBUFFER, yourFramebufferID);
    // 设置视口匹配纹理的宽高
    glViewport(0, 0, width, height);
    // 禁用不需要的渲染状态(比如深度测试、混合)
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_BLEND);
    // 使用刚才的清除着色器程序
    glUseProgram(clearShaderProgram);
    // 绘制3个顶点的三角形,覆盖整个缓冲区
    glDrawArrays(GL_TRIANGLES, 0, 3);
    // 恢复默认状态(可选,根据你的流程调整)
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glUseProgram(0);
    

方案二:用glTexSubImage2D填充内存数据(适合一次性清除)

如果只是偶尔需要清除缓冲区,这个方法更简单,直接用CPU生成全是-1的数据,然后更新整个纹理:

// 分配一块和纹理尺寸匹配的内存,全部填充为-1
std::vector<int> clearBuffer(width * height, -1);
// 绑定目标纹理
glBindTexture(GL_TEXTURE_2D, colorAttachmentID);
// 用填充好的数据更新整个纹理区域
glTexSubImage2D(
    GL_TEXTURE_2D, 0,          // 目标纹理、mip层级
    0, 0, width, height,       // 起始坐标和尺寸
    GL_RED_INTEGER, GL_INT,    // 格式和数据类型,要和纹理创建时一致
    clearBuffer.data()         // 数据指针
);

注意这里的GL_RED_INTEGERGL_INT必须和你创建纹理时的参数匹配(你创建时用了GL_R32I,所以这个是对的)。

两种方案对比

  • 方案一:GPU端操作,没有CPU-GPU数据拷贝,性能更好,适合频繁清除的场景(比如每帧都要清除拾取缓冲区)。
  • 方案二:代码更简洁,不需要额外的着色器,但大尺寸纹理会占用较多CPU内存,适合一次性或低频率的清除操作。

备注:内容来源于stack exchange,提问作者MeteorTequila

火山引擎 最新活动