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

Android OpenGL ES创建着色器时触发SIGSEGV崩溃求助

解决OpenGL ES中glCreateShader触发SIGSEGV崩溃的问题

崩溃原因分析

Fatal signal 11 (SEGV_MAPERR)在glCreateShader行,本质是OpenGL上下文未就绪时调用了GL API,或是在非GL线程(如主线程)执行了GL操作。glCreateShader必须在GLThread(Renderer的回调线程)中调用,且要确保GL上下文已绑定。

具体修复步骤

  • 将所有GL操作限制在Renderer回调方法内:
    若你的loadShader方法在主线程或Renderer初始化前调用,必然触发崩溃。必须把着色器加载、编译逻辑放在onSurfaceCreated方法中——该方法是GLThread在上下文就绪后才会调用的。
    正确实现示例:

    @Override
    public void onSurfaceCreated(GL10 unused, EGLConfig config) {
        // 在此处加载、编译着色器
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
        // 后续创建着色器程序等操作
    }
    
  • 完善loadShader方法的健壮性:
    确保传入的着色器代码非空且格式正确,同时添加编译错误检查(新手必备,便于排查问题):

    private int loadShader(int type, String shaderCode) {
        if (shaderCode == null || shaderCode.isEmpty()) {
            Log.e("OpenGL", "Shader code is empty or null");
            return 0;
        }
        int shader = GLES20.glCreateShader(type);
        GLES20.glShaderSource(shader, shaderCode);
        GLES20.glCompileShader(shader);
    
        // 检查编译状态
        int[] compileStatus = new int[1];
        GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compileStatus, 0);
        if (compileStatus[0] == GLES20.GL_FALSE) {
            Log.e("OpenGL", "Shader compile failed: " + GLES20.glGetShaderInfoLog(shader));
            GLES20.glDeleteShader(shader);
            return 0;
        }
        return shader;
    }
    
  • 规范GLSurfaceView初始化流程:
    在MainActivity中,确保GLSurfaceView在onCreate中初始化,设置Renderer后再显示:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        GLSurfaceView glView = new GLSurfaceView(this);
        glView.setRenderer(new YourRenderer());
        // 非连续渲染场景下,设为WHEN_DIRTY优化性能
        glView.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
        setContentView(glView);
    }
    

针对2D图像伪3D视差的简化实现建议(适合新手)

你只需基于传感器值实现伪3D效果,无需复杂深度图管线,可简化流程:

  • 用矩形(两个三角形)绘制2D图像,顶点数据包含纹理坐标和模拟深度值(可从深度图提取,或给不同区域设固定深度)。
  • 在顶点着色器中,根据传感器倾斜值(如加速度计x/y轴数据),对不同深度的顶点做偏移:
    // 顶点着色器示例
    attribute vec4 aPosition;
    attribute vec2 aTexCoord;
    attribute float aDepth;
    uniform vec2 uSensorOffset; // 传感器传入的偏移量,如(-0.01, 0.02)
    varying vec2 vTexCoord;
    
    void main() {
        // 深度越大,偏移量越大,实现视差效果
        vec4 offset = vec4(uSensorOffset * aDepth, 0.0, 0.0);
        gl_Position = aPosition + offset;
        vTexCoord = aTexCoord;
    }
    
  • 通过GLSurfaceView.queueEvent()将传感器数据传到Renderer,确保在GLThread中更新uniform变量:
    // MainActivity的传感器回调中
    glView.queueEvent(() -> {
        yourRenderer.updateSensorOffset(xOffset, yOffset);
        glView.requestRender();
    });
    

内容的提问来源于stack exchange,提问作者Mehmood Mir

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 09:07:04