Android Java 版本的 MSAA OpenGL ES 多重采样

最近多次被小伙伴问到 OpenGL 多重采样,其实前面文章里多次讲过了,就是构建2个缓冲区,多重采样缓冲区和目标解析缓冲区。

代码流程

c 复制代码
// Framebuffer IDs
private int msaaFBO;
private int msaaColorBuffer;
private int msaaDepthBuffer;

private int resolveFBO;
private int resolveTexture;

public void initFramebuffers(int width, int height) {
    // Step 1: Create MSAA FBO
    int[] fbo = new int[1];
    GLES30.glGenFramebuffers(1, fbo, 0);
    msaaFBO = fbo[0];
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, msaaFBO);

    // Create MSAA color buffer
    int[] renderbuffer = new int[1];
    GLES30.glGenRenderbuffers(1, renderbuffer, 0);
    msaaColorBuffer = renderbuffer[0];
    GLES30.glBindRenderbuffer(GLES30.GL_RENDERBUFFER, msaaColorBuffer);
    GLES30.glRenderbufferStorageMultisample(GLES30.GL_RENDERBUFFER, 4, GLES30.GL_RGBA8, width, height); // 4x MSAA
    GLES30.glFramebufferRenderbuffer(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_RENDERBUFFER, msaaColorBuffer);

    // Create MSAA depth buffer
    GLES30.glGenRenderbuffers(1, renderbuffer, 0);
    msaaDepthBuffer = renderbuffer[0];
    GLES30.glBindRenderbuffer(GLES30.GL_RENDERBUFFER, msaaDepthBuffer);
    GLES30.glRenderbufferStorageMultisample(GLES30.GL_RENDERBUFFER, 4, GLES30.GL_DEPTH_COMPONENT16, width, height);
    GLES30.glFramebufferRenderbuffer(GLES30.GL_FRAMEBUFFER, GLES30.GL_DEPTH_ATTACHMENT, GLES30.GL_RENDERBUFFER, msaaDepthBuffer);

    if (GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER) != GLES30.GL_FRAMEBUFFER_COMPLETE) {
        throw new RuntimeException("MSAA Framebuffer is not complete!");
    }

    // Step 2: Create Resolve FBO
    GLES30.glGenFramebuffers(1, fbo, 0);
    resolveFBO = fbo[0];
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, resolveFBO);

    // Create texture for resolved result
    int[] texture = new int[1];
    GLES30.glGenTextures(1, texture, 0);
    resolveTexture = texture[0];
    GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, resolveTexture);
    GLES30.glTexImage2D(GLES30.GL_TEXTURE_2D, 0, GLES30.GL_RGBA, width, height, 0, GLES30.GL_RGBA, GLES30.GL_UNSIGNED_BYTE, null);
    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_LINEAR);
    GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_LINEAR);
    GLES30.glFramebufferTexture2D(GLES30.GL_FRAMEBUFFER, GLES30.GL_COLOR_ATTACHMENT0, GLES30.GL_TEXTURE_2D, resolveTexture, 0);

    if (GLES30.glCheckFramebufferStatus(GLES30.GL_FRAMEBUFFER) != GLES30.GL_FRAMEBUFFER_COMPLETE) {
        throw new RuntimeException("Resolve Framebuffer is not complete!");
    }

    // Unbind framebuffer
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);
}

public void renderScene() {
    // Step 3: Render to MSAA FBO
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, msaaFBO);
    GLES30.glClear(GLES30.GL_COLOR_BUFFER_BIT | GLES30.GL_DEPTH_BUFFER_BIT);

    // Render your scene here...

    // Step 4: Resolve to texture
    GLES30.glBindFramebuffer(GLES30.GL_READ_FRAMEBUFFER, msaaFBO);
    GLES30.glBindFramebuffer(GLES30.GL_DRAW_FRAMEBUFFER, resolveFBO);
    GLES30.glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GLES30.GL_COLOR_BUFFER_BIT, GLES30.GL_NEAREST);

    // Step 5: Unbind framebuffers
    GLES30.glBindFramebuffer(GLES30.GL_FRAMEBUFFER, 0);

    // Step 6: Use resolveTexture for further processing (e.g., render to screen)
    renderQuadWithTexture(resolveTexture);
}
相关推荐
lzhdim27 分钟前
提高 SQL 语句执行速度的方法
java·开发语言·数据库·sql·oracle
深漂的华哥1 小时前
Ruoyi-Plus前后端分离场景下,数据加密传输
java·spring boot·后端·开源·maven·ruoyi
又见情义2 小时前
RK3568 Android 13 板载驱动适配-USB
android·arm开发·驱动开发
落魄大学生之流水线上谋生计2 小时前
Java锁全面指南:从基础概念到企业级应用
java·开发语言
delta_hell2 小时前
【阅读源码-Android】动画之Choreographer-2
android·源码·choreographer
mmsx3 小时前
基于 Android 的博物馆文化展示与预约 App —— 设计与实现(有源码和文档)
android·app·源码·文档
爱学习的小白柏4 小时前
【AI问数技术】多Agent协同架构:查询规划/SQL生成/洞察分析/报告生成
java·网络·人工智能·windows·sql·架构·llama
码匠许师傅4 小时前
【C++ 面试真题】30. 聊聊 C++ 的互斥锁与读写锁
java·c++·面试
一笑的小酒馆4 小时前
AndroidAGP9.0升级之路
android
沙盘客4 小时前
AFSIM 示例解读(03)· 六自由度飞行仿真 six_dof(下):机场运作与弹道导弹投送
java·javascript·经验分享