GVKun编程网logo

在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃(使用软件opengl选项已在)

1

如果您对在使用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选项已在)

在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃(使用软件opengl选项已在)

如何解决在使用 OpenGLES 2.0 的 Android 上使用 Gaffer 的固定时间戳时出现口吃

我的游戏循环出现了一些细微的卡顿。 我正确地实现了(我认为)来自 https://gafferongames.com/post/fix_your_timestep/

的固定时间戳技术

我认为当技术正确实施时,精灵运动是完全平滑的。我的代码没有产生 100% 的平滑,但一点也不差。

表面类:

  1. public static final int FRAME_RATE = 30;
  2. public static final double DELTA_TIME = 1/(double)FRAME_RATE;
  3. private double lastTimeStamp;
  4. private double accumulator;
  5. // An entity position in the game
  6. public float oldX,x;
  7. @Override
  8. public void onDrawFrame(GL10 unused) {
  9. double Now = (System.nanoTime() - lastTimeStamp)/1000000 * 0.001;
  10. if (Now > 0.25) {
  11. Now = 0.25;
  12. }
  13. lastTimeStamp = System.nanoTime();
  14. accumulator += Now;
  15. while (accumulator >= DELTA_TIME) {
  16. tick(DELTA_TIME);
  17. accumulator -= DELTA_TIME;
  18. }
  19. double alpha = accumulator/DELTA_TIME;
  20. render(alpha);
  21. }
  22. public void tick(double dt) {
  23. oldX = x;
  24. x++; // increment entity x position
  25. }
  26. public void render(double alpha) {
  27. float xx = (x - oldX) * (float)alpha + oldX; // interpolated x position
  28. ShaderBasic.render(fooTexture,xx,0); // render class
  29. }

着色器类:

  1. public void render(Texture texture,float x,float y) {
  2. //RENDERING
  3. gluseProgram(glIdProgram);
  4. //VERTICES
  5. glEnabLevertexAttribArray(glPosition);
  6. glVertexAttribPointer(glPosition,2,GL_FLOAT,false,texture.vertexBuffer);
  7. //UVS
  8. glEnabLevertexAttribArray(gluv);
  9. glVertexAttribPointer(gluv,texture.uvBuffer[0]);
  10. //MODEL
  11. gluniform2f(glTrans,x,y);
  12. //RENDERING
  13. glActiveTexture(GL_TEXTURE0);
  14. glBindTexture(GL_TEXTURE_2D,texture.glIdTexture);
  15. gluniform1i(glTexture,0);
  16. glDrawElements(GL_TRIANGLES,6,GL_UNSIGNED_SHORT,texture.indexBuffer);
  17. //disABLE
  18. gldisabLevertexAttribArray(glPosition);
  19. gldisabLevertexAttribArray(gluv);
  20. glBindTexture(GL_TEXTURE_2D,0);

}

顶点着色器部分:

  1. void main() {
  2. mat4 model = mat4(1.0,0.0,1.0,v_trans.x,v_trans.y,1.0);
  3. mat4 projection = mat4(0.0036764,0.0041666,1.0);
  4. gl_Position = projection * model * vec4(v_position,1.0);
  5. v_texCoord = v_uv;

}

纹理加载器类:

  1. private void loadImage(String imgPath,int frames) throws IOException {
  2. int[] id = new int[1];
  3. glGenTextures(1,id,0);
  4. Bitmap img = BitmapFactory.decodeStream(Utils.getAssets().open(imgPath));
  5. glBindTexture(GL_TEXTURE_2D,id[0]);
  6. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // question
  7. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_EDGE);
  8. glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_EDGE);
  9. glutils.texImage2D(GL_TEXTURE_2D,img,0);
  10. glBindTexture(GL_TEXTURE_2D,0);
  11. glIdTexture = id[0];
  12. width = img.getWidth();
  13. height = img.getHeight();
  14. this.frameWidth = width/frames;
  15. this.frameHeight = height;
  16. img.recycle();
  17. }

另一个问题:当我们使用小数部分大于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 方式的离屏渲染

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,单单说离屏渲染的流程如下:

  1. 创建一个帧缓冲的 buffer,取名为 FrameBuffer(一块显存)。

  2. 将要绘制的纹理数据写入 FrameBuffer(即绑定)。

  3. 在渲染的任意时刻将帧缓冲 FrameBuffer 中的数据取出使用(在你想用的任意时刻)。

 

对比直接绘制到屏幕的渲染流程如下:

  1. 将要绘制的纹理数据写入默认的帧缓冲,取名 defaultFrameBuffer。

  2. 在渲染的过程中连续的将 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纹理不是半透明而是二进制透明

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 图像交叉显示错误!

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 实现结构

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 实现结构的相关信息,请在本站查询。

本文标签: