我使用GLSurfaceView遇到了不同的行为.
AFAIK是程序的责任,清除每帧的缓冲区(颜色和深度).这意味着如果我不清除缓冲区,我会得到最后一帧的内容(或者之前用于双缓冲的内容).
似乎无论在某些设备上是什么,缓冲区都被清除了.我在Addison Wesley OpenglES2.0编程指南中对一些具有不同结果的测试设备进行了“Hello Triangle”程序的以下修改:
> Acer Iconia A500(4.0.3):未清除(预期行为)
> Sony XPERIA Go(4.0.4):已清除
> Galaxy S3(4.1.1):清除
> LG Optimus 4x HD(4.0.3):未清除
>三星Galaxy Tab 20.1(4.0.4):未清除
>摩托罗拉Xoom(3.2):未清除
> Galaxy S2(4.1.2 – rooted):清除
有没有办法强制在每个绘制回调中获得一个未更改的缓冲区?
清除屏幕的设备的结果如下所示:
测试活动如下所示:
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,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,x+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,1);
// Load the vertex data
GLES20.glVertexAttribPointer(0,3,GLES20.GL_FLOAT,false,vertexBuffer);
GLES20.glEnableVertexAttribArray(0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLES,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,"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