gpt4 book ai didi

android - GLSurfaceView onDrawFrame 清除行为

转载 作者:塔克拉玛干 更新时间:2023-11-02 21:05:29 25 4
gpt4 key购买 nike

我遇到了 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):清除

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

清除屏幕的设备的结果如下所示: cleared screen uncleared screen - expected behavior

测试 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/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com