【问题标题】:OpenGL ES Stencil Buffer not working on specific devicesOpenGL ES 模板缓冲区不适用于特定设备
【发布时间】:2014-03-04 04:19:18
【问题描述】:

我正在使用 OpenGL ES 2.0,并使用模板缓冲区。下面是我制作的一个简单的模板缓冲区演示的代码。模板只能在一台设备上正常工作。

设备如下:

Android 4.2.2、PowerVR SGX 544MP (GPU)、Allwinner A10 平板电脑。 (Stencil Buffer 在此设备上完美运行)

Android 4.1.2、Adreno 225 (GPU)、Galaxy S III 手机。 (Stencil Buffer 不工作,有些闪烁的stencil 鬼影很少。

Android 4.2.2、Mali-400MP (GPU)、瑞芯微 rk30sdk 平板电脑。 (在最初的测试中,Stencil Buffer 无法正常工作,经过多次更改后,它现在似乎可以正常工作,状态值得怀疑。修复运行中 Stencil Buffer 的具体更改目前未知)

相同的最新 .APK 给出了上述结果。

来自“Play Store”的应用程序“OpenGL 3D Showcase”在所有三个设备上运行,并且“showcase”#18“Stencil Buffer Shadows”[OGL 1.1] 完美运行,没有错误消息。源代码随应用提供,经审核无效。

下面是我的模板代码:

public void onDrawFrame(GL10 glUnused) {
    // Clear the rendering surface.
     glClear( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );

    multiplyMM(viewProjectionMatrix, 0, projectionMatrix, 0, viewMatrix, 0);

    invertM(invertedViewProjectionMatrix, 0, viewProjectionMatrix, 0);

    //Start using the stencil
    glEnable( GL_STENCIL_TEST );
    //Disable rendering to the color buffer
    glColorMask( false, false, false, false );


   //Place a 1 where rendered
   glStencilFunc( GL_ALWAYS, 1, 1 );

   //Replace where rendered
   glStencilOp( GL_REPLACE, GL_REPLACE, GL_REPLACE );

   glDisable(GL_DEPTH_TEST); 

   glStencilMask(0xFF);//value used when writing to stencil buffer      

    // draw stencil triangle
    rotateObjectInScene(0.0f, 0.0f, 0.0f);//x,y,z Object is rottated one full rotation ever 3 seconds within
    colorProgram.useProgram();
    colorProgram.setUniforms(modelViewProjectionMatrix, 0f, 0f, 1f);
    DemoTriangleStencilObj.bindData(colorProgram);
    DemoTriangleStencilObj.draw();

    //Reenable color
    glColorMask( true, true, true, true );
    //Where a 1 was not rendered
    glStencilFunc( GL_EQUAL, 1, 1 );//GL_EQUAL GL_NOTEQUAL
    //Keep the pixel
    glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );

    glStencilMask(0x00);//disable writing to stencil buffer by setting value used to 0.

    positionObjectInScene1(0.0f, 0.0f, 0.0f);//leave image/object fixed in center of screen
    textureProgram1.useProgram();
    textureProgram1.setUniforms(modelViewProjectionMatrix, texture_opengl);
    openglImageDemoObj.bindData(textureProgram1);
    openglImagerectanDemoObj.draw();

    //Finished using stencil
    glDisable( GL_STENCIL_TEST );

}

初始化:

public void onSurfaceCreated(GL10 glUnused, EGLConfig config) {
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

}

public void onSurfaceChanged(GL10 glUnused, int width, int height) {
    // Set the OpenGL viewport to fill the entire surface.
    glViewport(0, 0, width, height);

    // Landscape
    orthoM(projectionMatrix, 0, -1, 1, -1f, 1f, -1f, 20f);

    setLookAtM(viewMatrix, 0, 0f, 2.0f, 0.1f, 0.0f, 0f, 0f, 0f, 1f, 0f);

}

初始化2:

已尝试所有已注释的“setEGLConfigChooser”调用。

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Remove title bar
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    //Remove notification bar
    this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
    //setContentView(R.layout.activity_fist_open_glproject_aactivity);
    glSurfaceView = new GLSurfaceView(this);
    final TheSurfaceRenderer theSurfaceRenderer = new TheSurfaceRenderer(this);

    this.getApplicationContext();
    final ActivityManager activityManager =
            (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
    final ConfigurationInfo configurationInfo =
            activityManager.getDeviceConfigurationInfo();
    //final boolean supportsEs2 = false;//configurationInfo.reqGlEsVersion >= 0x20000;
    final boolean supportsEs2 = configurationInfo.reqGlEsVersion >= 0x20000;

    if (supportsEs2) {
        // Request an OpenGL ES 2.0 compatible context.
        glSurfaceView.setEGLContextClientVersion(2);

        //glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 0);//when use emulator, may be needed.
        glSurfaceView.setEGLConfigChooser(new MultiSampleConfigChooser());
        //glSurfaceView.setEGLConfigChooser(8, 8, 8, 8, 16, 8);
        //glSurfaceView.setEGLConfigChooser(5,6,5,0,24,8);
        //glSurfaceView.setEGLConfigChooser(5,6,5,0,16,8);
        //glSurfaceView.setEGLConfigChooser(5,6,5,8,16,8);

        // Assign our renderer.
        //glSurfaceView.setRenderer(new AirHockeyRenderer(this));
        glSurfaceView.setRenderer(theSurfaceRenderer);
        rendererSet = true;
        //Toast.makeText(this, "Renderer started", Toast.LENGTH_LONG).show();
    } else {
        Toast.makeText(this, "This device does not support OpenGL ES 2.0.",
        Toast.LENGTH_LONG).show();
        return;
    }

    setContentView(glSurfaceView);
}

有什么想法可以跟踪问题吗?我还能从哪里获得帮助?(如果需要,可以联系 MFG/Android/Google 获得帮助吗?)

【问题讨论】:

  • 有这方面的消息吗?在某些设备上存在类似的闪烁问题。

标签: android opengl-es stencil-buffer


【解决方案1】:

在您提供的代码中,您先设置 glStencilMask(0xFF),然后再设置 glStencilMask(0x00)。 OpenGL 是一个状态机,所以无论你最后设置什么都是当前值——即使你清除了。默认模板掩码值为 255,因此您的 glClear 在第一帧上工作。但在那之后,模板掩码为 0(因为你是这样设置的),所以模板缓冲区不会被清除。在函数顶部执行此操作:

public void onDrawFrame(GL10 glUnused) {
    // Clear the rendering surface.
    glStencilMask(0xFF);
    glClear( GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT );
    ...
}

glStencilMask 函数设置写入掩码——清除是一种写入操作,因此您通常应该在清除时将所有模板位设置为可写入。

【讨论】:

    猜你喜欢
    • 2011-03-09
    • 2020-04-10
    • 2014-12-18
    • 1970-01-01
    • 2012-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多