OpenGL ES 3.0 and newer on android

About the multisampling issue I’m facing, just in case anyone can help me with that.

in GLRenderer.setReadDrawBuffers methid, last section

            .......
            } else {
                RenderBuffer rb = fb.getColorBuffer(fb.getTargetIndex());
                // select this draw buffer
                if (context.boundDrawBuf != rb.getSlot()) {
                    if(gl2!=null) {
                        gl2.glDrawBuffer(GLFbo.GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
                    } else {
                        gles30.glDrawBuffer(GLFbo.GL_COLOR_ATTACHMENT0_EXT + rb.getSlot());
                    }
                    context.boundDrawBuf = rb.getSlot();
                }
            }
            .......

As there’s no glDrawBuffer in GLES but glDrawBuffers exists (glDrawBuffers - OpenGL ES 3 Reference Pages) and does the same work so I’m wrapping it this way:

public void glDrawBuffer(int mode) {
    tmpBuff.clear();
    tmpBuff.put(0, mode);
    tmpBuff.rewind();
    glDrawBuffers(tmpBuff);
}

public void glDrawBuffers(IntBuffer bufs) {
    GLES30.glDrawBuffers(bufs.limit(), bufs);
}

Depending on the framebuffer his call is returning a GL_INVALID_ENUM which according to the documentation linked: " GL_INVALID_ENUM is generated if one of the values in bufs is not an accepted value."

I’ve check that the color attachment is in the valid range ( < MAX_COLOR_ATTACHMENTS ) for all cases but I’ve not found any reason for that.

In adition to that, the call to glBlitFramebuffer (glBlitFramebuffer - OpenGL ES 3 Reference Pages) at GLRenderer.copyFrameBuffer is returning GL_INVALID_OPERATION error and capturing with renderdoc, it finds the error “glblitframebuffer color attachment must have identical formats when resolving” which I also don’t know how to address.

Thanks

    tmpBuff.clear();
    tmpBuff.put(0, mode);
    tmpBuff.rewind();

How long is the tmpBuff? This gives me the impression that it is longer than 1, if that’s the case, you need to set the limit or glDrawBuffers will try to bind a bunch of 0 id buffers. If the buffer is 1 element long, then you don’t need rewind and clear.

Sorry, I forgot to specify it. Yes, it’s a IntBuffer just one element long

IntBuffer tmpBuff = BufferUtils.createIntBuffer(1);

I’ve been deeper into it and DrawBuffer was giving error just the first run but blit was always setting the GL_INVALID_OPERATION error. I’ve not found a reason for that so I’ve just disabled all multisampling related code to continue with the other stuff. If I think of something or anyone gives me ideas on this I may get back to it but for the time being I think I’ll leave it for the future or for other people more experienced in opengl

Hi!

Just curious if any of you owning any mobile running gles3.2 could please try the PBRLighting test. For this test the background env map uses RGB16F and I changed the EnvCamera to use RGBA16F instead.

According to the specs (https://www.khronos.org/registry/OpenGL/specs/es/3.2/es_spec_3.2.pdf - page 163) RGB16F can be used as texture and RGBA16F should be renderable but my SGS6 doesn’t render the background and fails to setup the framebuffer with GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT

I’ve found this post stating more or less the same issue in SGS6 and the solution is “The version of the driver in the Galaxy S6 doesn’t support floating point render targets; it is supported in the newer r8p0 driver onwards.”
https://community.arm.com/developer/tools-software/graphics/f/discussions/6060/mali-t760-incomplete_attachment-when-attach-a-texture-with-floating-point-format-to-framebuffer
The weird stuff here is that it’s a 4 year old post and my device is fully updated to latest samsung rom (august/2018) so I’m not sure if it’s my device issue or something I did wrong

Thanks

I don’t have any android devices anymore, but just thought I’d pop this here in case you didn’t know about it.

1 Like

Thanks @jayfella I didn’t know about this service :wink:

Hi!

I’ve came across some other complicate stuff. According to the specs most floating point textures are supported in GLES3 and newer although with some restrictions so I tried to add them (or at least some of them) to jme so we have full HDR, PBR and so working in android.

Just adding them to the GLImageFormats was giving failures (incomplete framebuffer attachment in the engine) but the issue was that setting the texture (glTexImage2D call) to use those formats failed with GL_INVALID_OPERATION (1282 - 0x0500).

At first I though it was some device related issue (as said in my last post) but then, once I was able to test other devices I found that all behaved the same, so it was not a device issue but a code issue.

I found this resource: GitHub - ARM-software/opengl-es-sdk-for-android: OpenGL ES SDK for Android which among others, it has a multisample fbo example using rgba16f and rgba32f which worked in my devices not having texture_float and texture_half_float extensions (on gles30 and newer it just adds filtering and blending capability). Then I got deeper into it and ported this sample to java just in case it was a C++ vs java issue in android (weird but possible) and it worked. Then I also created a small test for jme just creating a framebuffer with the same format just to check if there was any aditional gl call or any different parameter that could make it fail but everything is the same.

Here’s the code and output for all the tests

Simple java gles floating point texture sample (working):

package com.fbotest;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

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

import android.content.Context;
import android.opengl.GLES30;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.GLSurfaceView.Renderer;

public class GLRendererClean implements Renderer
{
    private Context context;
    private GLSurfaceView view;

    private boolean testFBO=false;
    private int [] formatsToTest={GLES30.GL_RGB16F, GLES30.GL_RGBA16F, GLES30.GL_RGBA32F, GLES30.GL_RGB10_A2};
    private int currentTestFormat=2;

    private int frame=0;


    public GLRendererClean(Context context, GLSurfaceView view)
    {
        this.context=context;
        this.view=view;
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config)
    {
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
        GLES20.glDepthFunc(GLES20.GL_LEQUAL);

        GLES20.glPixelStorei(GLES20.GL_UNPACK_ALIGNMENT, 1);
    }

    @Override
    public void onDrawFrame(GL10 gl)
    {
        ++frame;
        if(frame%1000==0)
        {
            this.runTestFBO();
        }
        drawGL2();
        if(testFBO)
        {
            this.realTestFBO();
            testFBO=false;
        }
    }

    private void drawGL1(GL10 gl)
    {
    }

    private void drawGL2()
    {

        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_STENCIL_BUFFER_BIT);

        GLES20.glClearColor(1.0f, 1.0f, 0.0f, 1.0f);

        //Set Scene information to the renderer
        GLES20.glEnable(GLES20.GL_CULL_FACE);
        GLES20.glCullFace(GLES20.GL_BACK);
        GLES20.glEnable(GLES20.GL_DEPTH_TEST);
        GLES20.glDepthRangef(0,1);
        GLES20.glDepthFunc(GLES20.GL_LEQUAL);

        GLES20.glEnable(GLES20.GL_BLEND);
        GLES20.glBlendFunc(GLES20.GL_SRC_ALPHA, GLES20.GL_ONE_MINUS_SRC_ALPHA);

    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height)
    {
        gl.glViewport(0, 0, width, height);
        gl.glMatrixMode(GL10.GL_PROJECTION);
        float ratio = (float)width / (float)height;
        gl.glLoadIdentity();
        gl.glFrustumf(-ratio, ratio, -1, 1, 3, 7);

        GLES20.glViewport(0, 0, width, height);
    }

    void setTextureFiltering(int texture)
    {
        /* If the new texture format doesn't support linear filtering, disable it. */
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, texture);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_NEAREST);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_NEAREST);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
    }

    boolean setupFBO(IntBuffer fbo, IntBuffer colorBuffer, IntBuffer depthBuffer, int textureSize, int internalFormat, int samples)
    {
        GLES20.glGenFramebuffers(1, fbo);
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, fbo.get(0));

        /* Generate and attach depth buffer. */
        GLES20.glGenRenderbuffers(1, depthBuffer);
        GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, depthBuffer.get(0));
        System.err.println("Error post getRbDepth: " + GLES20.glGetError());

            GLES20.glRenderbufferStorage(GLES20.GL_RENDERBUFFER, GLES20.GL_DEPTH_COMPONENT16, textureSize, textureSize);
            System.err.println("Error post RbStorage: " + GLES20.glGetError());
        GLES20.glFramebufferRenderbuffer(GLES20.GL_FRAMEBUFFER, GLES20.GL_DEPTH_ATTACHMENT, GLES20.GL_RENDERBUFFER, depthBuffer.get(0));

        /* Generate and attach texture for color buffer. */
        GLES20.glGenTextures(1, colorBuffer);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, colorBuffer.get(0));
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAX_LEVEL, 0);
        if(internalFormat==GLES30.GL_RGBA16F)
        {
            System.err.println("RGBA16F ");
            System.err.println(GLES20.GL_TEXTURE_2D + ","+ 0 + "," + internalFormat + "," + textureSize + "," + textureSize + "," + 0 + "," + GLES20.GL_RGBA + "," + GLES30.GL_HALF_FLOAT + "," + null);
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, internalFormat, textureSize, textureSize, 0, GLES20.GL_RGBA, GLES30.GL_HALF_FLOAT, null);
        }
        else if(internalFormat==GLES30.GL_RGB16F)
        {
            System.err.println("RGB16F ");
            System.err.println(GLES20.GL_TEXTURE_2D + ","+ 0 + "," + internalFormat + "," + textureSize + "," + textureSize + "," + 0 + "," + GLES20.GL_RGB + "," + GLES30.GL_HALF_FLOAT + "," + null);
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, internalFormat, textureSize, textureSize, 0, GLES20.GL_RGB, GLES30.GL_HALF_FLOAT, null);
        }
        else if(internalFormat==GLES30.GL_RGBA32F)
        {
            System.err.println("RGBA32F ");
            System.err.println(GLES20.GL_TEXTURE_2D + ","+ 0 + "," + internalFormat + "," + textureSize + "," + textureSize + "," + 0 + "," + GLES20.GL_RGBA + "," + GLES20.GL_FLOAT + "," + null);
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, internalFormat, textureSize, textureSize, 0, GLES20.GL_RGBA, GLES20.GL_FLOAT, null);
        }
        else if(internalFormat==GLES30.GL_RGB10_A2)
        {
            System.err.println("GL_RGB10_A2 ");
            System.err.println(GLES20.GL_TEXTURE_2D + ","+ 0 + "," + internalFormat + "," + textureSize + "," + textureSize + "," + 0 + "," + GLES20.GL_RGBA + "," + GLES30.GL_UNSIGNED_INT_2_10_10_10_REV + "," + null);
            GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, internalFormat, textureSize, textureSize, 0, GLES20.GL_RGBA, GLES30.GL_UNSIGNED_INT_2_10_10_10_REV, null);
        }
        System.err.println("Error post TexImage2D: " + GLES20.glGetError());

        setTextureFiltering(colorBuffer.get(0));
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

            GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER, GLES20.GL_COLOR_ATTACHMENT0, GLES20.GL_TEXTURE_2D, colorBuffer.get(0), 0);
            System.err.println("Error post FbTex2D: " + GLES20.glGetError());

        /* Ensure the framebuffer is 'complete'. */
        int fbStatus=GLES20.glCheckFramebufferStatus(GLES20.GL_FRAMEBUFFER);
        if (fbStatus != GLES20.GL_FRAMEBUFFER_COMPLETE)
        {
            System.err.println((samples>1 ? "Multisampled" : "Non-multisampled") + " framebuffer is incomplete! " + fbStatus + " Error code " + GLES20.glGetError());
        }
        else
        {
            System.err.println("Framebuffer complete!");
        }

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

        GLES20.glBindRenderbuffer(GLES20.GL_RENDERBUFFER, 0);
        System.err.println("Error post unbind: " + GLES20.glGetError());


        return true;
    }

    public boolean realTestFBO()
    {
        IntBuffer fbo=ByteBuffer.allocateDirect(1*4).order(ByteOrder.nativeOrder()).asIntBuffer();
        fbo.put(0,0);
        fbo.position(0);
        IntBuffer colorBuffer=ByteBuffer.allocateDirect(1*4).order(ByteOrder.nativeOrder()).asIntBuffer();
        colorBuffer.put(0,0);
        colorBuffer.position(0);
        IntBuffer depthBuffer=ByteBuffer.allocateDirect(1*4).order(ByteOrder.nativeOrder()).asIntBuffer();
        depthBuffer.put(0,0);
        depthBuffer.position(0);

        return setupFBO(fbo, colorBuffer, depthBuffer, 1024, formatsToTest[currentTestFormat], 1);
    }

    public void runTestFBO()
    {
        this.testFBO=true;
        currentTestFormat=(currentTestFormat+1)%formatsToTest.length;
    }
}

Output of the test:

07-13 03:22:14.517 19285 19358 W System.err: Error post getRbDepth: 1282
07-13 03:22:14.524 19285 19358 W System.err: Error post RbStorage: 0
07-13 03:22:14.525 19285 19358 W System.err: GL_RGB10_A2 
07-13 03:22:14.526 19285 19358 W System.err: 3553,0,32857,1024,1024,0,6408,33640,null
07-13 03:22:14.531 19285 19358 W System.err: Error post TexImage2D: 0
07-13 03:22:14.531 19285 19358 W System.err: Error post FbTex2D: 0
07-13 03:22:14.532 19285 19358 W System.err: Framebuffer complete!
07-13 03:22:14.532 19285 19358 W System.err: Error post unbind: 0

07-13 03:22:31.394 19285 19358 W System.err: Error post getRbDepth: 0
07-13 03:22:31.400 19285 19358 W System.err: Error post RbStorage: 0
07-13 03:22:31.401 19285 19358 W System.err: RGB16F 
07-13 03:22:31.401 19285 19358 W System.err: 3553,0,34843,1024,1024,0,6407,5131,null
07-13 03:22:31.408 19285 19358 W System.err: Error post TexImage2D: 0
07-13 03:22:31.408 19285 19358 W System.err: Error post FbTex2D: 0
07-13 03:22:31.408 19285 19358 W System.err: Framebuffer complete!
07-13 03:22:31.409 19285 19358 W System.err: Error post unbind: 0

07-13 03:22:48.273 19285 19358 W System.err: Error post getRbDepth: 0
07-13 03:22:48.283 19285 19358 W System.err: Error post RbStorage: 0
07-13 03:22:48.285 19285 19358 W System.err: RGBA16F 
07-13 03:22:48.285 19285 19358 W System.err: 3553,0,34842,1024,1024,0,6408,5131,null
07-13 03:22:48.299 19285 19358 W System.err: Error post TexImage2D: 0
07-13 03:22:48.300 19285 19358 W System.err: Error post FbTex2D: 0
07-13 03:22:48.301 19285 19358 W System.err: Framebuffer complete!
07-13 03:22:48.301 19285 19358 W System.err: Error post unbind: 0

07-13 03:23:05.157 19285 19358 W System.err: Error post getRbDepth: 0
07-13 03:23:05.167 19285 19358 W System.err: Error post RbStorage: 0
07-13 03:23:05.168 19285 19358 W System.err: RGBA32F 
07-13 03:23:05.168 19285 19358 W System.err: 3553,0,34836,1024,1024,0,6408,5126,null
07-13 03:23:05.191 19285 19358 W System.err: Error post TexImage2D: 0
07-13 03:23:05.191 19285 19358 W System.err: Error post FbTex2D: 0
07-13 03:23:05.191 19285 19358 W System.err: Framebuffer complete!
07-13 03:23:05.191 19285 19358 W System.err: Error post unbind: 0

The jme3 fbo test (not working):
package com.jme.test;

import com.jme3.app.SimpleApplication;
import com.jme3.renderer.opengl.GLRenderer;
import com.jme3.texture.FrameBuffer;
import com.jme3.texture.Image;
import com.jme3.texture.Texture2D;

public class TextFBO extends SimpleApplication {

    FrameBuffer fb;
    int frame=0;

    @Override
    public void simpleInitApp() {
        System.out.println("JOLIVER - Starting");

        fb = new FrameBuffer(1024, 1024, 1);
        fb.setDepthBuffer(Image.Format.Depth);
        Texture2D tex=new Texture2D(1024,1024,Image.Format.RGBA16F);
        fb.setColorTexture(tex);
        fb.setUpdateNeeded();
    }

    @Override
    public void simpleUpdate(float tpf) {
        if(frame<1)
        {
            ((GLRenderer)this.getRenderer()).updateFrameBuffer(fb);
        }
        frame++;
    }
}

It’s trace and exception output:

07-13 03:03:10.021 10190 10239 I System.out: GetString(VERSION) = "OpenGL ES 3.2 v1.r15p0-00rel0.68b65ac7cf15907aeb95fa944f39eef2"
07-13 03:03:10.022 10190 10239 I System.out: GetString(EXTENSIONS) = "GL_EXT_debug_marker GL_ARM_rgba8 GL_ARM_mali_shader_binary GL_OES_depth24 GL_OES_depth_texture GL_OES_depth_texture_cube_map GL_OES_packed_depth_stenc..."
07-13 03:03:10.022 10190 10239 I System.out: GetInteger(MAX_VERTEX_TEXTURE_IMAGE_UNITS, out=16)
07-13 03:03:10.023 10190 10239 I System.out: GetInteger(MAX_TEXTURE_IMAGE_UNITS, out=16)
07-13 03:03:10.023 10190 10239 I System.out: GetInteger(MAX_FRAGMENT_UNIFORM_VECTORS, out=1024)
07-13 03:03:10.023 10190 10239 I System.out: GetInteger(MAX_VERTEX_UNIFORM_VECTORS, out=1024)
07-13 03:03:10.023 10190 10239 I System.out: GetInteger(MAX_VERTEX_ATTRIBS, out=16)
07-13 03:03:10.023 10190 10239 I System.out: GetInteger(MAX_TEXTURE_SIZE, out=8192)
07-13 03:03:10.023 10190 10239 I System.out: GetInteger(MAX_CUBE_MAP_TEXTURE_SIZE, out=4096)
07-13 03:03:10.024 10190 10239 I System.out: GetInteger(MAX_RENDERBUFFER_SIZE, out=8192)
07-13 03:03:10.024 10190 10239 I System.out: GetInteger(MAX_COLOR_ATTACHMENTS, out=4)
07-13 03:03:10.024 10190 10239 I System.out: GetString(VENDOR) = "ARM"
07-13 03:03:10.024 10190 10239 I System.out: GetString(RENDERER) = "Mali-T760"
07-13 03:03:10.025 10190 10239 I System.out: GetString(VERSION) = "OpenGL ES 3.2 v1.r15p0-00rel0.68b65ac7cf15907aeb95fa944f39eef2"
07-13 03:03:10.025 10190 10239 I System.out: GetString(SHADING_LANGUAGE_VERSION) = "OpenGL ES GLSL ES 3.20"
07-13 03:03:10.026 10190 10239 I System.out: PixelStorei(UNPACK_ALIGNMENT, 1)
07-13 03:03:10.390 10190 10239 I System.out: GenFramebuffers(out=1)
07-13 03:03:10.390 10190 10239 I System.out: BindFramebuffer(FRAMEBUFFER, 1)
07-13 03:03:10.391 10190 10239 I System.out: GenRenderbuffers(out=1)
07-13 03:03:10.391 10190 10239 I System.out: BindRenderbuffer(RENDERBUFFER, 1)
07-13 03:03:10.400 10190 10239 I System.out: RenderbufferStorage(RENDERBUFFER, DEPTH_COMPONENT16, 1024, 1024)
07-13 03:03:10.400 10190 10239 I System.out: FramebufferRenderbuffer(FRAMEBUFFER, DEPTH_ATTACHMENT, RENDERBUFFER, 1)
07-13 03:03:10.400 10190 10239 I System.out: GenTextures(out=1)
07-13 03:03:10.401 10190 10239 I System.out: BindTexture(TEXTURE_2D, 1)
07-13 03:03:10.401 10190 10239 I System.out: TexParameteri(TEXTURE_2D, TEXTURE_MAX_LEVEL, 0)
07-13 03:03:10.402 10190 10239 I System.out: GetError() = ZERO
07-13 03:03:10.402 10190 10239 I System.out: TexImage2D(TEXTURE_2D, 0, RGBA16F, 1024, 1024, 0, RGBA, HALF_FLOAT, null)
07-13 03:03:10.402 10190 10239 I System.out: GetError() = INVALID_OPERATION
07-13 03:03:10.403 10190 10239 I System.out: TexParameteri(TEXTURE_2D, TEXTURE_MAG_FILTER, NEAREST)
07-13 03:03:10.403 10190 10239 I System.out: TexParameteri(TEXTURE_2D, TEXTURE_MIN_FILTER, NEAREST)
07-13 03:03:10.403 10190 10239 I System.out: TexParameteri(TEXTURE_2D, TEXTURE_WRAP_T, CLAMP_TO_EDGE)
07-13 03:03:10.403 10190 10239 I System.out: TexParameteri(TEXTURE_2D, TEXTURE_WRAP_S, CLAMP_TO_EDGE)
07-13 03:03:10.404 10190 10239 I System.out: FramebufferTexture2D(FRAMEBUFFER, COLOR_ATTACHMENT0, TEXTURE_2D, 1, 0)
07-13 03:03:10.404 10190 10239 I System.out: CheckFramebufferStatus(FRAMEBUFFER) = FRAMEBUFFER_INCOMPLETE_ATTACHMENT
07-13 03:03:10.412 10190 10239 E com.jme3.app.AndroidHarnessFragment: Grave Exception thrown in Thread[GLThread 19989,5,main]
07-13 03:03:10.412 10190 10239 E com.jme3.app.AndroidHarnessFragment: java.lang.IllegalStateException: Framebuffer has erronous attachment.
....

The parameters in both executions are exactly the same although the first one is outputted in decimal format instead of GL constants

I’ve also checked if the EGL configuration was the same, if the gles3 context was properly defined and initialized and so on but I’ve just run out of ideas. Any help is appreciated

Sorry for the long post :sweat_smile:

Thanks

1 Like

Found it!!!

In AndroidGL it’s using format instead of internalFormat for third parameter:

public void glTexImage2D(int target, int level, int internalFormat, int width, int height, int border, int format, int type, ByteBuffer data) {
    GLES20.glTexImage2D(target, level, format, width, height, 0, format, type, data);
}

Fixed it and everything works finally!!! :clap: :clap: :clap:

7 Likes

Multisampling works on android finally the framebuffer blit error was related with badly configured formats and I’ve decided to create the PR because I won’t be able to continue working with this for a month so I prefer to integrate it to master although there’s some small issues still

https://github.com/jMonkeyEngine/jmonkeyengine/pull/1147

4 Likes

Cool, thank you so much @joliver82

Hi!

I’m thinking that IOS could benefit from these changes also. Maybe a quick update on the jme3-ios project making com.jme3.renderer.ios.IosGL implementing also GL2 and GLES_30 same way AndroidGL does and adding the proper opengl native methods to com.jme3.renderer.ios.JmeIosGLES should suffice or in the wort case adding some little changes while initializing the GL context.

I’ve never developed anything for IOS and even worst, although I’ve read the jme3-ios package code I don’t know how natives are called from java. There’s plenty of methods in the JmeIosGLES class but I’ve not found any related C code :confused: Maybe any IOS developer over here could lead this change :thinking:

@joliver82 I am considering to merge your Android openGL ES 3 support PR today, can I go ahead and merge it? IOS changes probably going to be in a separate PR, Yes?

1 Like

Sure! From my point of view, if noone has any concern it’s ok to merge it :wink:

About the ios yes, it would be other PR hopefully from other developer (I’m feeling too lazy to learn ios dev and also I don’t own a mac neither an ios phone) :sweat_smile:

**EDIT
I was curious about where the native code would be and finally found that everything is in the sdk repo instead of engine’s, in the templates path:

opengl context initialization → sdk/jmeAppDelegate.m at master · jMonkeyEngine/sdk · GitHub
opengl native calls → sdk/JmeIosGLES.m at master · jMonkeyEngine/sdk · GitHub

Should be somehow easy to add required gl functions… Although GLES is deprecated by apple in favor of metal, I think it’s interesting to have gles3 in ios also, so I may create a new topic about this in the ios subforum or in contribution just in case anyone can help with it

1 Like