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

OpenGL ES中Kotlin实现Compute Shader无效果问题求助

问题排查:Compute Shader无效果导致纹理始终为黑色

核心问题概述

测试Compute Shader与片段Shader联动:预期Compute Shader将1x1纹理设为白色,片段Shader用该纹理颜色绘制屏幕底部区域,但实际Compute Shader未生效,纹理始终为RGBA(0,0,0,0),底部区域显示黑色。

关键错误点及修复方案

1. Compute Shader程序未正确创建链接

原代码中createComputeProgram仅编译了Compute Shader对象,未创建并链接成完整的GL程序。Compute Shader必须像顶点/片段Shader一样,附着到Program对象并完成链接才能执行。

修复代码:

private fun createComputeProgram(): Int {
    val computeShader = compileShader(GLES31.GL_COMPUTE_SHADER, computeCode)
    return GLES31.glCreateProgram().also { program ->
        GLES31.glAttachShader(program, computeShader)
        GLES31.glLinkProgram(program)

        val linkStatus = IntArray(1)
        GLES31.glGetProgramiv(program, GLES31.GL_LINK_STATUS, linkStatus, 0)
        if (linkStatus[0] == 0) {
            val infoLog = GLES31.glGetProgramInfoLog(program)
            GLES31.glDeleteProgram(program)
            GLES31.glDeleteShader(computeShader)
            throw RuntimeException("Compute Program linking failed: $infoLog")
        }
        // 链接完成后删除Shader对象,已不再需要
        GLES31.glDeleteShader(computeShader)
    }
}

2. 纹理内部格式与Compute Shader绑定格式不匹配

创建纹理时使用GL_RGBA8(8位整数格式),但Compute Shader绑定的是RGBA32F(32位浮点格式),格式不兼容导致写入操作无效。

修复代码:
修改createTextures中的glTexImage2D参数:

GLES31.glTexImage2D(
    GLES31.GL_TEXTURE_2D,
    0,
    GLES31.GL_RGBA32F,   // 改为与Compute Shader匹配的浮点格式
    1,
    1,
    0,
    GLES31.GL_RGBA,
    GLES31.GL_FLOAT,
    null
)

3. 读取纹理像素的方法错误

glReadPixels用于读取当前绑定的帧缓冲像素,而非纹理像素。要读取纹理内容,需使用glGetTexImage。

修复代码:

fun readAndLogPixelFromTexture(texture: Int) {
    val pixelData = FloatArray(4)
    GLES31.glBindTexture(GLES31.GL_TEXTURE_2D, textures[texture])
    // 使用glGetTexImage读取纹理数据
    GLES31.glGetTexImage(GLES31.GL_TEXTURE_2D, 0, GLES31.GL_RGBA, GLES31.GL_FLOAT, java.nio.FloatBuffer.wrap(pixelData))

    val r = pixelData[0]
    val g = pixelData[1]
    val b = pixelData[2]
    val a = pixelData[3]
    Timber.d("SET-COLOR: R: $r, G: $g, B: $b, A: $a")
}

4. 片段Shader采样坐标冗余(非核心但需修正)

单个像素纹理的采样坐标任意值都能取到唯一像素,但vec2(1.0)超出标准纹理坐标范围(通常是[0,1]),虽有CLAMP_TO_EDGE参数兜底,但建议使用vec2(0.5)或直接省略坐标(单个像素纹理采样坐标不影响结果)。

修复代码:

// 替换片段Shader中的采样代码
gl_FragColor = texture2D(ColorSet, vec2(0.5));

验证步骤

  1. 确保所有修复代码替换完成后,重新编译运行。
  2. 查看日志输出,纹理像素应显示为RGBA(1.0,1.0,1.0,1.0)。
  3. 屏幕底部区域将显示白色,符合预期效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 23:32:02