草庐IT

android - GLSurfaceView onDrawFrame 清除行为

coder 2023-12-03 原文

我遇到了 GLSurfaceView 的不同行为。 据我所知,程序有责任清除每一帧的缓冲区(颜色和深度)。这意味着如果我不清除缓冲区,我会得到最后一帧的内容(或之前的双缓冲帧)。

似乎无论在某些设备上如何清除缓冲区。我在一些测试设备上运行 Addison Wesley OpenglES2.0 编程指南中的“Hello Triangle”程序的以下修改,结果不同:

  • Acer Iconia A500 (4.0.3):清除(预期行为)
  • 索尼 XPERIA Go (4.0.4):清除
  • Galaxy S3 (4.1.1):清除
  • LG Optimus 4x HD (4.0.3):通过
  • Samsung Galaxy Tab 20.1 (4.0.4):清除
  • 摩托罗拉 Xoom(3.2):通过
  • Galaxy S2(4.1.2 - root):清除

有没有办法在每次绘制回调时强制获取未更改的缓冲区?

清除屏幕的设备的结果如下所示:

测试 Activity 如下所示:

package com.example.glcleartest;

import java.nio.Buffer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;

public class MainActivity extends Activity {

protected static final int NUM_VERTICES = 3;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    GLSurfaceView glview = (GLSurfaceView) findViewById(R.id.glview);
    glview.setEGLConfigChooser(false);
    glview.setEGLContextClientVersion(2);
    glview.setRenderer(new Renderer() {

        private int programObject;
        private FloatBuffer vertexBuffer;

        @Override
        public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        }

        @Override
        public void onSurfaceChanged(GL10 gl, int width, int height) {
            GLES20.glViewport(0, 0, width, height);
            init();
        }

        @Override
        public void onDrawFrame(GL10 gl) {
            float x = 0.1f*(float) Math.sin(System.currentTimeMillis()/1000.0);
            float[] vVertices = new float[]{x, 0.5f, 0.0f,
                    x-0.5f, -0.5f, 0.0f,
                    x+0.5f, -0.5f, 0.0f};
            vertexBuffer.rewind();
            vertexBuffer.put(vVertices);
            vertexBuffer.rewind();


            // Use the program object
            GLES20.glUseProgram(programObject);
            int handle = GLES20.glGetUniformLocation(programObject, "uColor");
            float r = (float) (0.5f+Math.sin(System.currentTimeMillis()/1000.0));
            float g = (float) (0.5f+Math.sin(System.currentTimeMillis()/300.0));
            GLES20.glUniform4f(handle, r, g,0,1);

            // Load the vertex data
            GLES20.glVertexAttribPointer(0, 3, GLES20.GL_FLOAT, false, 0, vertexBuffer);
            GLES20.glEnableVertexAttribArray(0);
            GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, 3);             
        }

        private void error(String s) {
            Log.e("GLTEST", s);
        }

        private int loadShader(int shaderType, String source) {
            if (shaderType != GLES20.GL_FRAGMENT_SHADER && shaderType != GLES20.GL_VERTEX_SHADER) {
                throw new RuntimeException("Illegal shader type");
            }

            int shader = GLES20.glCreateShader(shaderType);
            if (shader != 0) {
                GLES20.glShaderSource(shader, source);
                GLES20.glCompileShader(shader);
                int[] compiled = new int[1];
                GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
                if (compiled[0] == 0) {
                    error("Could not compile shader :");
                    error(GLES20.glGetShaderInfoLog(shader));
                    GLES20.glDeleteShader(shader);
                    shader = 0;
                    throw new RuntimeException("Shader Syntax / compilation error");
                }
            }
            return shader;
        }

        private void init() {
            String vShaderStr = "attribute vec4 vPosition; \n" + 
                                    "void main() \n" + "{ \n" + 
                                    " gl_Position = vPosition; \n" + 
                                    "} \n";
            String fShaderStr = "precision mediump float; \n" +
                                        "uniform vec4 uColor;" +
                                        "void main() \n" + 
                                        "{ \n" + 
                                        " gl_FragColor = uColor; \n" + 
                                        "} \n";

            ByteBuffer vbb = ByteBuffer.allocateDirect(NUM_VERTICES*3*4);
            vbb.order(ByteOrder.nativeOrder());
            vertexBuffer = vbb.asFloatBuffer();

            int vertexShader;
            int fragmentShader;

            // Load the vertex/fragment shaders
            vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vShaderStr);
            fragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fShaderStr);

            // Create the program object
            programObject = GLES20.glCreateProgram();
            if (programObject == 0)
                return;

            GLES20.glAttachShader(programObject, vertexShader);
            GLES20.glAttachShader(programObject, fragmentShader);
            // Bind vPosition to attribute 0
            GLES20.glBindAttribLocation(programObject, 0, "vPosition");
            // Link the program
            GLES20.glLinkProgram(programObject);
            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(programObject, GLES20.GL_LINK_STATUS, linkStatus, 0);

            if (linkStatus[0] != GLES20.GL_TRUE) {
                error("Could not link program: ");
                error(GLES20.glGetProgramInfoLog(programObject));
                GLES20.glDeleteProgram(programObject);
                programObject = 0;
            }
        }
    });
}
}

最佳答案

如果你想在交换后保留你的后台缓冲区内容,你必须将交换表面的 EGL_SWAP_BEHAVIOR 属性设置为 EGL_BUFFER_PRESERVED,如 EGL API 中所述.请注意,尽管在大多数平台上,这将是一个相当很大的性能损失。在大多数情况下,您最好重新绘制框架。

有关历史:请参阅 http://www.khronos.org/registry/egl/specs/EGLTechNote0001.html

关于android - GLSurfaceView onDrawFrame 清除行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14581938/

有关android - GLSurfaceView onDrawFrame 清除行为的更多相关文章

  1. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  2. ruby - 如何在 Ubuntu 中清除 Ruby Phusion Passenger 的缓存? - 2

    我试过重新启动apache,缓存的页面仍然出现,所以一定有一个文件夹在某个地方。我没有“公共(public)/缓存”,那么我还应该查看哪些其他地方?是否有一个URL标志也可以触发此效果? 最佳答案 您需要触摸一个文件才能清除phusion,例如:touch/webapps/mycook/tmp/restart.txt参见docs 关于ruby-如何在Ubuntu中清除RubyPhusionPassenger的缓存?,我们在StackOverflow上找到一个类似的问题:

  3. 安卓apk修改(Android反编译apk) - 2

    最近因为项目需要,需要将Android手机系统自带的某个系统软件反编译并更改里面某个资源,并重新打包,签名生成新的自定义的apk,下面我来介绍一下我的实现过程。APK修改,分为以下几步:反编译解包,修改,重打包,修改签名等步骤。安卓apk修改准备工作1.系统配置好JavaJDK环境变量2.需要root权限的手机(针对系统自带apk,其他软件免root)3.Auto-Sign签名工具4.apktool工具安卓apk修改开始反编译本文拿Android系统里面的Settings.apk做demo,具体如何将apk获取出来在此就不过多介绍了,直接进入主题:按键win+R输入cmd,打开命令窗口,并将路

  4. ruby - Ruby gsub 替换中的行为不一致? - 2

    两个gsub产生不同的结果。谁能解释一下为什么?代码也可在https://gist.github.com/franklsf95/6c0f8938f28706b5644d获得.ver=9999str="\tCFBundleDevelopmentRegion\n\ten\n\tCFBundleVersion\n\t0.1.190\n\tAppID\n\t000000000000000"putsstr.gsub/(CFBundleVersion\n\t.*\.).*()/,"#{$1}#{ver}#{$2}"puts'--------'putsstr.gsub/(CFBundleVersio

  5. ruby-on-rails - Ruby 中意外的大小写行为 - 2

    我在一段非常简单的代码(如我所想)中得到了一个错误的值:org=4caseorgwhenorg=4val='H'endputsval=>nil请不要生气,我希望我错过了一些非常明显的东西,但我真的想不通。谢谢。 最佳答案 这是典型的Ruby错误。case有两种被调用的方法,一种是你传递一个东西作为分支的基础,另一种是你不传递的东西。如果您确实在case中指定了一个表达式语句然后评估所有其他条件并与===进行比较.在这种情况下org评估为false和org===false显然不是真的。所有其他情况也是如此,它们要么是真的,要么是假的。

  6. ruby - 使对象的行为类似于 ruby​​ 中并行分配的数组 - 2

    假设您在Ruby中执行此操作:ar=[1,2]x,y=ar然后,x==1和y==2。是否有一种方法可以在我自己的类中定义,从而产生相同的效果?例如rb=AllYourCode.newx,y=rb到目前为止,对于这样的赋值,我所能做的就是使x==rb和y=nil。Python有这样一个特性:>>>classFoo:...def__iter__(self):...returniter([1,2])...>>>x,y=Foo()>>>x1>>>y2 最佳答案 是的。定义#to_ary。这将使您的对象被视为要分配的数组。irb>o=Obje

  7. ruby - 了解在 Ruby 中与 lambda 一起使用的 inject 行为 - 2

    我经常将预配置的lambda插入可枚举的方法中,例如“map”、“select”等。但是“注入(inject)”的行为似乎有所不同。例如与mult4=lambda{|item|item*4}然后(5..10).map&mult4给我[20,24,28,32,36,40]但是,如果我制作一个2参数lambda用于像这样的注入(inject),multL=lambda{|product,n|product*n}我想说(5..10).inject(2)&multL因为“inject”有一个可选的单个初始值参数,但这给了我......irb(main):027:0>(5..10).inject

  8. ruby-on-rails - 清除 GitLab 中的所有 Assets - 2

    我想在我公司安装的GitLab中使用自定义Logo-白色、Logo-黑色和网站图标。我用谷歌搜索了我的屁股并尝试了所有我能找到的方法来清除这些该死的图像,但似乎没有任何效果。这是唯一似乎成功运行但未删除图像的进程:bundleexecrakecache:clearRAILS_ENV=productionservicegitlabstopredis-cliFLUSHALLbundleexecrakeassets:precompileRAILS_ENV=productionservicegitlabstart然后我清除我的浏览器缓存并转到该域,再次出现相同的该死的图像!我什至删除了我能从应

  9. ruby - 奇怪的 ruby​​ for 循环行为(为什么这样做有效) - 2

    defreverse(ary)result=[]forresult[0,0]inaryendresultendassert_equal["baz","bar","foo"],reverse(["foo","bar","baz"])这行得通,我想了解原因。有什么解释吗? 最佳答案 如果我使用each而不是for/in重写它,它看起来像这样:defreverse(ary)result=[]#forresult[0,0]inaryary.eachdo|item|result[0,0]=itemendresultendforainb基本上就

  10. ruby - 比较 rspec 中的 float 时的奇怪行为 - 2

    以下测试中的第3个失败:specify{(0.6*2).shouldeql(1.2)}specify{(0.3*3).shouldeql(0.3*3)}specify{(0.3*3).shouldeql(0.9)}#thisonefails这是为什么呢?这是浮点问题还是ruby​​或rspec问题? 最佳答案 从rspec-2.1开始specify{(0.6*2).shouldbe_within(0.01).of(1.2)}在那之前:specify{(0.6*2).shouldbe_close(1.2,0.01)}

随机推荐