如果您对在使用OpenGLES2.0的Android上使用Gaffer的固定时间戳时出现口吃感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于在使用OpenGLES2.0的An
如果您对在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃感兴趣,那么本文将是一篇不错的选择,我们将为您详在本文中,您将会了解到关于在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃的详细内容,我们还将为您解答使用软件opengl选项已在的相关问题,并且为您提供关于1.OpenGLES——FBO 方式的离屏渲染、android / opengles alpha纹理不是半透明而是二进制透明、Android opengles 图像交叉显示错误!、Android OpenGLES 实现结构的有价值信息。
本文目录一览:- 在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃(使用软件opengl选项已在)
- 1.OpenGLES——FBO 方式的离屏渲染
- android / opengles alpha纹理不是半透明而是二进制透明
- Android opengles 图像交叉显示错误!
- Android OpenGLES 实现结构
在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃(使用软件opengl选项已在)
如何解决在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃
我的游戏循环出现了一些细微的卡顿。 我正确地实现了(我认为)来自 https://gafferongames.com/post/fix_your_timestep/
的固定时间戳技术我认为当技术正确实施时,精灵运动是完全平滑的。我的代码没有产生 100% 的平滑,但一点也不差。
表面类:
public static final int FRAME_RATE = 30;
public static final double DELTA_TIME = 1/(double)FRAME_RATE;
private double lastTimeStamp;
private double accumulator;
// An entity position in the game
public float oldX,x;
@Override
public void onDrawFrame(GL10 unused) {
double Now = (System.nanoTime() - lastTimeStamp)/1000000 * 0.001;
if (Now > 0.25) {
Now = 0.25;
}
lastTimeStamp = System.nanoTime();
accumulator += Now;
while (accumulator >= DELTA_TIME) {
tick(DELTA_TIME);
accumulator -= DELTA_TIME;
}
double alpha = accumulator/DELTA_TIME;
render(alpha);
}
public void tick(double dt) {
oldX = x;
x++; // increment entity x position
}
public void render(double alpha) {
float xx = (x - oldX) * (float)alpha + oldX; // interpolated x position
ShaderBasic.render(fooTexture,xx,0); // render class
}
着色器类:
public void render(Texture texture,float x,float y) {
//RENDERING
gluseProgram(glIdProgram);
//VERTICES
glEnabLevertexAttribArray(glPosition);
glVertexAttribPointer(glPosition,2,GL_FLOAT,false,texture.vertexBuffer);
//UVS
glEnabLevertexAttribArray(gluv);
glVertexAttribPointer(gluv,texture.uvBuffer[0]);
//MODEL
gluniform2f(glTrans,x,y);
//RENDERING
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texture.glIdTexture);
gluniform1i(glTexture,0);
glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_SHORT,texture.indexBuffer);
//disABLE
gldisabLevertexAttribArray(glPosition);
gldisabLevertexAttribArray(gluv);
glBindTexture(GL_TEXTURE_2D,0);
}
顶点着色器部分:
void main() {
mat4 model = mat4(1.0,0.0,1.0,v_trans.x,v_trans.y,1.0);
mat4 projection = mat4(0.0036764,0.0041666,1.0);
gl_Position = projection * model * vec4(v_position,1.0);
v_texCoord = v_uv;
}
纹理加载器类:
private void loadImage(String imgPath,int frames) throws IOException {
int[] id = new int[1];
glGenTextures(1,id,0);
Bitmap img = BitmapFactory.decodeStream(Utils.getAssets().open(imgPath));
glBindTexture(GL_TEXTURE_2D,id[0]);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // question
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
glutils.texImage2D(GL_TEXTURE_2D,img,0);
glBindTexture(GL_TEXTURE_2D,0);
glIdTexture = id[0];
width = img.getWidth();
height = img.getHeight();
this.frameWidth = width/frames;
this.frameHeight = height;
img.recycle();
}
另一个问题:当我们使用小数部分大于0的(x,y)坐标时,纹理过滤一定是GL_LINEAR吗?我注意到当我使用 GL_NEAREST 时,屏幕上渲染的精灵在屏幕的某些位置被切片。我认为 GL_NEAREST 当我们有十进制不精确时不会过滤所有的纹理像素......
谢谢!!!!
解决方法
我的代码没有产生 100% 的平滑,但一点也不差。
您是否始终达到 60 FPS?如果不是,那么您会遇到一些微卡顿,因为 Android OpenGL ES 使用三重缓冲和垂直同步,因此显示交换永远不会完全匹配您的应用程序端帧时序。
另一个问题:当我们使用小数部分大于0的(x,y)坐标时,纹理过滤一定是GL_LINEAR吗?我注意到当我使用 GL_NEAREST 时,屏幕上渲染的精灵在屏幕的某些位置被切片。我认为 GL_NEAREST 当我们有十进制不精确时不会过滤所有的纹理像素......
正确,顾名思义,GL_NEAREST
只返回距离采样点最近的纹素,没有进行任何过滤。对于不是 1:1 texel-to-pixel 的任何东西,它通常永远不会是您想要使用的。
以后每个帖子只能问一个问题。
1.OpenGLES——FBO 方式的离屏渲染
参考
https://blog.csdn.net/u011371324/article/details/78011211
书写本文的初衷是为了自我学习
出现背景
明确两个概念
-
窗口系统默认帧缓冲
-
应用程序帧缓冲
FBO (frame buffer object), 帧缓冲区对象,在 Android 中,绘制三角形一般都是直接重写 GLSurfaceView,因为 Android 已经集成好了 OpenGLES 的环境,渲染操作都是在默认的帧缓冲去做的,这个帧缓冲是我们在创建一个 Surface 的时候自动创建的(Surface, 第二节讲一下)。但这仅限于 demo 级别,实际应用中,如果我们需要渲染到纹理,往往不使用窗口系统默认提供的帧缓冲区域,需要自己创建了。
何为帧缓冲?
显示到屏幕上的每一帧数据其实对应的就是内存中的数据,在内存中对应分配着存储帧数据的缓冲区,包括写入颜色的颜色缓冲,写入深度值的深度缓冲,以及基于一些条件丢弃片元的模板缓冲,这几种缓冲一起称之为帧缓冲。
为什么要使用帧缓冲?
之前绘制使用的纹理都是使用图片加载得到的纹理,如果我们要对纹理在着色器中做一些处理,模糊、虚化、双屏、镜子等特效,那么使用帧缓冲可以很好的实现。此外,帧缓冲提供了一个很高效的机制,它能够快速的分离和附着纹理或渲染缓冲对象,这比在帧缓冲之间切换要快得多。
两种附件
纹理附件
纹理附件和通过图片加载的纹理类似,只不过这个纹理附加是通过渲染命令写入到纹理当中的,不是通过图片纹理得到的。
注意:除了附加颜色附件之外,还可以附件深度和模板纹理附件。例如,当我们开启了深度测试时,就需要附着一个深度附件,来表示深度信息,以便进行深度测试。为了附加一个深度缓冲,可用 GL_DEPTH_ATTACHMENT 作为附件类型。
渲染缓冲对象(RBO)
渲染缓冲对象(RenderBuffer Object,简称 RBO)是一个 OpenGL 格式的缓冲,即以 OpenG 原生 (native) 格式存储它的数据,因此它相当于是优化过的内部数据。当它绑定到 FrameBuffer 上时,渲染的像素信息就写到 RBO 中。
渲染缓冲对象将渲染数据存储到缓冲中,并且以原生格式存储,所以它成为一种快速可写入的介质。但是,只能写入,不能修改。RBO 常常用来存储深度和模板信息,用于深度测试和模板测试,而且比用纹理存储的深度和模板方式要快得多。RBO 可以用来实现双缓冲(double buffer)。
同样,渲染缓冲对象也可以写入颜色信息,然后将图像信息显示在屏幕上。
貌似 RBO 比纹理有点多,但也不是万能的,纹理自有纹理的优点,纹理能够在 shader 中进行操作或者需要读取像素时,做一些处理,此时 RBO 就无能为力了。
案例演示
网上的很多教程都只是说明了流程,然后演示的 demo 都混杂着各种其他的东西,初学者要费很大的力气才能理解。下面说明一个单纯只应用了 FBO 的案例:
环境是使用 Android 集成好的,GLSurfaceView ,egl 环境也是。(关于这一点,可以看下一个文档,介绍 EGL)。
撇开 OpenGLES 的 API,单单说离屏渲染的流程如下:
-
创建一个帧缓冲的 buffer,取名为 FrameBuffer(一块显存)。
-
将要绘制的纹理数据写入 FrameBuffer(即绑定)。
-
在渲染的任意时刻将帧缓冲 FrameBuffer 中的数据取出使用(在你想用的任意时刻)。
对比直接绘制到屏幕的渲染流程如下:
-
将要绘制的纹理数据写入默认的帧缓冲,取名 defaultFrameBuffer。
-
在渲染的过程中连续的将 defaultFrameBuffer 中的数据取出使用。
我们只是使用 OpenGLES 的 API 去完成上面的流程。
首先是工程结构,FBO 的实现应用了红线的几个文件(其他文件绘制了一个普通的三角形,):
MainActivity 指定了 View。
public class MainActivity extends AppCompatActivity {
private GLSurfaceView mGLView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mGLView = new MySurfaceView(this);
setContentView(mGLView);
}
}
MySurfaceView 指定了渲染器,渲染模式。onDrawFrame 开始离屏渲染。
public class MySurfaceView extends GLSurfaceView {
private MyRenderer mRenderer;
private FBORenderer fboRenderer;
public MySurfaceView (Context context){
super(context);
this.setEGLContextClientVersion(2);
// 绘制普通三角形的渲染器
// mRenderer=new MyRenderer(context);
// this.setRenderer(mRenderer);
fboRenderer = new FBORenderer(context);
this.setRenderer(fboRenderer);
this.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);
}
}
FBORenderer 重写了 GLSurfaceView 的渲染器
public class FBORenderer implements GLSurfaceView.Renderer{
public static int sScreenWidth;
public static int sScreenHeight;
private Shape_FBO mRectangle;
float yAngle;
float xAngle;
private Context mContext;
public FBORenderer(Context context) {
super();
mContext = context;
}
@Override
public void onSurfaceCreated(GL10 gl, EGLConfig config) {
GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1);
mRectangle = new Shape_FBO(mContext);
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
}
@Override
public void onSurfaceChanged(GL10 gl, int width, int height) {
sScreenWidth = width;
sScreenHeight = height;
GLES20.glViewport(0, 0, width, height);
Matrix.perspectiveM(mProjectionMatrix, 0, 45, (float)width/height, 2, 5);
Matrix.setLookAtM(mViewMatrix, 0, 0, 0, 3, 0, 0, 0, 0, 1, 0);
}
private final float[] mProjectionMatrix = new float[16];
private final float[] mViewMatrix = new float[16];
private final float[] mModuleMatrix = new float[16];
private final float[] mViewProjectionMatrix = new float[16];
private final float[] mMVPMatrix = new float[16];
@Override
public void onDrawFrame(GL10 gl) {
Matrix.setIdentityM(mModuleMatrix, 0);
Matrix.rotateM(mModuleMatrix, 0, xAngle, 1, 0, 0);
Matrix.rotateM(mModuleMatrix, 0, yAngle, 0, 1, 0);
Matrix.multiplyMM(mViewProjectionMatrix, 0, mProjectionMatrix, 0, mViewMatrix, 0);
Matrix.multiplyMM(mMVPMatrix, 0, mViewProjectionMatrix, 0, mModuleMatrix, 0);
// GLES20.glViewport(0, 0, 1024, 1024);
mRectangle.draw(mMVPMatrix, mModuleMatrix);
mRectangle.draw(mMVPMatrix, mModuleMatrix);
}
}
本类就是核心的绘制类了。
1.colorTextureId 这个纹理缓存指定到 FrameBuffer, 与 FrameBuffer 中的数据进行关联,也就是说,现在 colorTextureId 就是 FrameBuffer 中数据所生成的图片。
2. 在 FrameBuffer 中绘制读入的图片 mLoadedTextureId。
3. 在默认的窗口 defaultFrameBuffer 中绘制 colorTextureId。
对照代码理解这张图,更有体会。
一般情况我们都是直接走红线进行绘制,FBO 离屏渲染走绿线
可以在项目中 crtl+f ( GLES20.glBindTexture (GLES20.GL_TEXTURE_2D, colorTxtureId);
将其中的 colorTxtureId,替换为 mLoadedTextureId,
并注释 draw 方法中 /*================================================================*/ 以上的代码,你也会看到图片显示了出来。
首先是生成一张纹理 mLoadedTextureId,然后绑定到 FrameBuffer 中,然后
public class Shape_FBO {
private static String TAG = "ShapeFBO";
private FloatBuffer mSqureBuffer;
private FloatBuffer mSqureBufferfbo;
private int mFrameBufferProgram;
private int mWindowProgram;
private int mLoadedTextureId;
private Context mContext;
public Shape_FBO(Context context) {
this.mContext = context;
this.initVetexData();
}
public void initVetexData() {
// 生成纹理
mLoadedTextureId=initTexture(R.drawable.texture1);
// 准备绘制数据
float [] bgVertex = new float[] {
-1f,-1f, 0,1,
-1f,1f, 0,0,
1f,-1f, 1,1,
1f,1f, 1,0
};
ByteBuffer vbb0 = ByteBuffer.allocateDirect(bgVertex.length * 4);
vbb0.order(ByteOrder.nativeOrder());
mSqureBuffer = vbb0.asFloatBuffer();
mSqureBuffer.put(bgVertex);
mSqureBuffer.position(0);
float [] fboVertex = new float[] {
-1f,-1f, 0,1,
-1f,1f, 0,0,
1f,-1f, 1,1,
1f,1f, 1,0
};
ByteBuffer vbb1 = ByteBuffer.allocateDirect(fboVertex.length * 4);
vbb1.order(ByteOrder.nativeOrder());
mSqureBufferfbo = vbb1.asFloatBuffer();
mSqureBufferfbo.put(fboVertex);
mSqureBufferfbo.position(0);
}
public int initTexture(int res) {
Bitmap bitmap = BitmapFactory.decodeResource(mContext.getResources(), res);
int [] textures = new int[1];
GLES20.glGenTextures(1, textures, 0);
// 绑定纹理缓存到纹理单元
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textures[0]);
// 设置采样,拉伸方式
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_MIRRORED_REPEAT);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_MIRRORED_REPEAT);
// 指定纹理图片生成 2D 纹理
GLUtils.texImage2D(GLES20.GL_TEXTURE_2D, 0, bitmap, 0);
// 释放 bitmap
bitmap.recycle();
// 解除绑定
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
return textures[0];
}
public void draw(float[] mvpMatrix, float[] mMatrix) {
// 生成 FrameBuffer
int [] framebuffers = new int[1];
GLES20.glGenFramebuffers(1, framebuffers, 0);
// 生成 Texture
int [] textures = new int[2];
GLES20.glGenTextures(2, textures, 0);
int colorTxtureId = textures[0];
// 绑定纹理缓存到纹理单元
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, colorTxtureId);
// 设置采样,拉伸方式
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,GLES20.GL_NEAREST);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,GLES20.GL_TEXTURE_MAG_FILTER,GLES20.GL_LINEAR);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S,GLES20.GL_MIRRORED_REPEAT);
GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T,GLES20.GL_MIRRORED_REPEAT);
// 生成 2D 纹理
GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGB, FBORenderer.sScreenWidth, FBORenderer.sScreenHeight,0, GLES20.GL_RGB, GLES20.GL_UNSIGNED_SHORT_5_6_5, null);
// 绑定 framebuffer
int framebufferId = framebuffers[0];
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, framebufferId);
// 挂载 textureID 到 framebufferId
GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, colorTxtureId, 0);
if (GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER)== GLES20.GL_FRAMEBUFFER_COMPLETE) {
Log.e("shapefbo", "glFramebufferTexture2D error");
}
int frameBufferVertexShader = loaderShader(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
int frameBufferFagmentShader = loaderShader(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);
mFrameBufferProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mFrameBufferProgram, frameBufferVertexShader);
GLES20.glAttachShader(mFrameBufferProgram, frameBufferFagmentShader);
GLES20.glLinkProgram(mFrameBufferProgram);
int positionHandle1 = GLES20.glGetAttribLocation(mFrameBufferProgram, "aPosition");
int textureCoordHandle1 = GLES20.glGetAttribLocation(mFrameBufferProgram, "aTextureCoord");
int textureHandle1 = GLES20.glGetUniformLocation(mFrameBufferProgram, "uTexture");
mSqureBufferfbo.position(0);
GLES20.glVertexAttribPointer(positionHandle1, 2, GLES20.GL_FLOAT, false, (2+2) * 4, mSqureBufferfbo);
mSqureBufferfbo.position(2);
GLES20.glVertexAttribPointer(textureCoordHandle1, 2, GLES20.GL_FLOAT, false, (2+2) * 4, mSqureBufferfbo);
GLES20.glEnableVertexAttribArray(positionHandle1);
GLES20.glEnableVertexAttribArray(textureCoordHandle1);
// GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mLoadedTextureId);
GLES20.glUniform1i(textureHandle1, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER,0);
/*================================================================*/
// 切换到窗口系统的缓冲区
GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
int vertexShader = loaderShader(GLES20.GL_VERTEX_SHADER, windowVertexShaderCode);
int fragmentShader = loaderShader(GLES20.GL_FRAGMENT_SHADER, windowFragmentShaderCode);
mWindowProgram = GLES20.glCreateProgram();
GLES20.glAttachShader(mWindowProgram, vertexShader);
GLES20.glAttachShader(mWindowProgram, fragmentShader);
GLES20.glLinkProgram(mWindowProgram);
GLES20.glUseProgram(mWindowProgram);
int positionHandle = GLES20.glGetAttribLocation(mWindowProgram, "aPosition");
int textureCoordHandle = GLES20.glGetAttribLocation(mWindowProgram, "aTextureCoord");
int textureHandle = GLES20.glGetUniformLocation(mWindowProgram, "uTexture");
mSqureBuffer.position(0);
GLES20.glVertexAttribPointer(positionHandle, 2, GLES20.GL_FLOAT, false, (2+2) * 4, mSqureBuffer);
mSqureBuffer.position(2);
GLES20.glVertexAttribPointer(textureCoordHandle, 2, GLES20.GL_FLOAT, false, (2+2) * 4, mSqureBuffer);
GLES20.glEnableVertexAttribArray(positionHandle);
GLES20.glEnableVertexAttribArray(textureCoordHandle);
GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, colorTxtureId);
GLES20.glUniform1i(textureHandle, 0);
GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);
GLES20.glDeleteTextures(2, textures, 0);
GLES20.glDeleteFramebuffers(1, framebuffers, 0);
}
private int loaderShader(int type, String shaderCode) {
int shader = GLES20.glCreateShader(type);
GLES20.glShaderSource(shader, shaderCode);
GLES20.glCompileShader(shader);
return shader;
}
private String windowVertexShaderCode = ""
+ "attribute vec2 aPosition;"
+ "attribute vec2 aTextureCoord;"
+ "varying vec2 vTextureCoord;"
+ "void main(){"
+ "gl_Position = vec4(aPosition,0,1);"
+ "vTextureCoord = aTextureCoord;"
+ "}";
private String windowFragmentShaderCode = "precision mediump float;"
+ "uniform sampler2D uTexture;"
+ "varying vec2 vTextureCoord;"
+ "void main(){"
+ "gl_FragColor = texture2D(uTexture, vTextureCoord);"
+ "}";
private String vertexShaderCode = ""
+ "attribute vec2 aPosition;"
+ "attribute vec2 aTextureCoord;"
+ "varying vec2 vTextureCoord;"
+ "void main(){"
+ "gl_Position = vec4(aPosition,0,1);"
+ "vTextureCoord = aTextureCoord;"
+ "}";
private String fragmentShaderCode = "precision mediump float;"
+ "uniform sampler2D uTexture;"
+ "varying vec2 vTextureCoord;"
+ "void main(){"
+ "gl_FragColor = texture2D(uTexture, vTextureCoord);"
+ "}";
GitHub 地址欢迎点星星
android / opengles alpha纹理不是半透明而是二进制透明
我正在使用alpha通道绘制一些纹理,但是当它们显示时,它看起来像alpha通道只是二进制.因此像素是透明的或不透明的,尽管在纹理文件本身中像素是半透明的.混合设置如下:
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_ONE,GL10.GL_ONE_MINUS_SRC_ALPHA);
这个问题有解决方法吗?
以上显示了它应该如何,以下显示它是如何:
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA,GL10.GL_ONE_MINUS_SRC_ALPHA);
gl.glEnable(GL10.GL_ALPHA_BITS);
//draw...
gl.gldisable(GL10.GL_ALPHA_BITS);
Android opengles 图像交叉显示错误!
Android opengles 图像交叉显示错误!
opengles1.0版本
利用 glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, triangles); 绘制两个4边形;
EGL_DEPTH_SIZE = 16; 深度测试都已开启;
当两个图像平行时深度测试有效,显示正确;
当两个图像交叉时显示错误。
图片:http://dev.10086.cn/cmdn/bbs/thread-32638-1-1.html
请各位大侠帮忙分析一下错误原因,急!非常感谢!
Android OpenGLES 实现结构
OpenGL实现路径:
frameworks/native/opengl/libs/Android.mk
该makefile里面会编译出libEGL libGLESv1_CM 以及 libGLESv2
这里Android是已经实现了一套opengl的, 具体实现接口在: frameworks/native/opengl/libs/EGL/egl_entries.in
在这里面包含很多常见的opengl接口:
EGL_ENTRY(EGLDisplay, eglGetDisplay, NativeDisplayType)
EGL_ENTRY(EGLBoolean, eglInitialize, EGLDisplay, EGLint*, EGLint*)
EGL_ENTRY(EGLBoolean, eglTerminate, EGLDisplay)
EGL_ENTRY(EGLBoolean, eglGetConfigs, EGLDisplay, EGLConfig*, EGLint, EGLint*)
EGL_ENTRY(EGLBoolean, eglChooseConfig, EGLDisplay, const EGLint *, EGLConfig *, EGLint, EGLint *)
.........
该路径下Loader.cpp是加载具体opengl实现的逻辑:
1. 读取配置system/lib/egl/egl.cfg, 配置如下:
#0 0 android
0 1 mali
因此变量dpy=0, impl = 1, tag = mali, 默认也可能是dpy=0, impl = 0, tag = android。
2. 根据第一步的tag加载相应的库,如果tag是android则加载驱动:
如下代码优先加载libGLES, 如果使用Android原生实现库加载libGLES_android, 厂家也可以具体实现
if (tag) {
dso = load_driver("GLES", tag, cnx, EGL | GLESv1_CM | GLESv2);
if (dso) {
hnd = new driver_t(dso);
} else {
// Always load EGL first
dso = load_driver("EGL", tag, cnx, EGL);
if (dso) {
hnd = new driver_t(dso);
// TODO: make this more automated
hnd->set( load_driver("GLESv1_CM", tag, cnx, GLESv1_CM), GLESv1_CM );
hnd->set( load_driver("GLESv2", tag, cnx, GLESv2), GLESv2 );
}
}
}
libGLES_android实现path: frameworks/native/opengl/libagl/Android.mk
3. 通过dlsym读取库实现函数填充connection->egl, gHooks[egl_connection_t::GLESv1_INDEX], gHooks[egl_connection_t::GLESv2_INDEX]
这部分由第一次eglGetDisplay, eglGetDisplay实现EGL/egl.cpp 头文件EGL/egl.h
在eglGetDisplay中会去初始化驱动,最终调用到egl_init_drivers_locked函数中。这个函数的主要内容如下
EGLBoolean egl_init_drivers_locked()
{
if (sEarlyInitState) {
// initialized by static ctor. should be set here.
return EGL_FALSE;
}
// get our driver loader
Loader& loader(Loader::getInstance());
// dynamically load all our EGL implementations for all displays
// and retrieve the corresponding EGLDisplay
// if that fails, don''t use this driver.
// TODO: currently we only deal with EGL_DEFAULT_DISPLAY
egl_connection_t* cnx;
egl_display_t* d = &gDisplay[0];
cnx = &gEGLImpl[IMPL_SOFTWARE];
if (cnx->dso == 0) {
cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_SOFTWARE];
cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_SOFTWARE];
cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 0, cnx);
if (cnx->dso) {
EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for software EGL!");
d->disp[IMPL_SOFTWARE].dpy = dpy;
if (dpy == EGL_NO_DISPLAY) {
loader.close(cnx->dso);
cnx->dso = NULL;
}
}
}
cnx = &gEGLImpl[IMPL_HARDWARE];
if (cnx->dso == 0) {
char value[PROPERTY_VALUE_MAX];
property_get("debug.egl.hw", value, "1");
if (atoi(value) != 0) {
cnx->hooks[GLESv1_INDEX] = &gHooks[GLESv1_INDEX][IMPL_HARDWARE];
cnx->hooks[GLESv2_INDEX] = &gHooks[GLESv2_INDEX][IMPL_HARDWARE];
cnx->dso = loader.open(EGL_DEFAULT_DISPLAY, 1, cnx);
if (cnx->dso) {
EGLDisplay dpy = cnx->egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
LOGE_IF(dpy==EGL_NO_DISPLAY, "No EGLDisplay for hardware EGL!");
d->disp[IMPL_HARDWARE].dpy = dpy;
if (dpy == EGL_NO_DISPLAY) {
loader.close(cnx->dso);
cnx->dso = NULL;
}
}
} else {
LOGD("3D hardware acceleration is disabled");
}
}
if (!gEGLImpl[IMPL_SOFTWARE].dso && !gEGLImpl[IMPL_HARDWARE].dso) {
return EGL_FALSE;
}
return EGL_TRUE;
}
egl_init_drivers_locked函数主要的工作就是填充gEGLImp数组变量,这个变量是egl_connection_t类型。还有一个工作就是填充gDisplay数组(只有一个元素)的disp[IMPL_HARDWARE].dpy以及disp[IMPLSOFTWAREWARE].dpy,填充的来源来自gEGLImpl【soft or hard】.egl.eglGetDisplay(EGL_DEFAULT_DISPLAY);
在Loader.cpp中的Loader::open中会加载对应的硬件和软件加速的驱动(动态链接库)。
软件的对应的是/system/lib/egl/libEGL_android.so,没有默认的硬件so,因此在硬件加速时,返回值hnd会指向NULL,在需要硬件加速时这个动态链接库需要进行实现。
LoadDriver函数会根据其第三个参数,决定加载egl/gles,glesv1_cm,glesv2驱动。
我们今天的关于在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃和使用软件opengl选项已在的分享已经告一段落,感谢您的关注,如果您想了解更多关于1.OpenGLES——FBO 方式的离屏渲染、android / opengles alpha纹理不是半透明而是二进制透明、Android opengles 图像交叉显示错误!、Android OpenGLES 实现结构的相关信息,请在本站查询。
本文标签: