OpenGL ES 2.0 Object Picking on iOS

后端 未结 2 720
暖寄归人
暖寄归人 2020-12-02 14:43

What is the best method to select objects that have been drawn in OpenGL ES 2.0 (iOS)?

I am drawing points.

2条回答
  •  轻奢々
    轻奢々 (楼主)
    2020-12-02 15:29

    Here is how i do, based on the above solution, with depth buffer for 3D picking and GLKVector3 signature to retrieve the seal :

    • all my objects got a seal
    • i use a GLKVector3 named color to retrieved the seal from the read pixel. With this solution you can store 255 *255 * 255 = 16,581,375 objects.

    In the Shader (vertex or fragment as you want)

    add a picking boolean which tell you if you do the pick pass or not

    uniform bool picking;
    

    and the GLKVector3

    uniform vec3 color;
    

    if the boolean picking is activated so the color will be the GLKVector3

    if(picking)
    {
        colorVarying = vec4(color, 1.0);
    }
    

    In the ViewController

    the method which create the GLKVector3 from a seal (when i create a new 3D object) :

    -(GLKVector3)pack:(uint)seal
    {
        GLKVector3 hash;
    
        float r = seal % 255;
        float g = (seal / 255) % 255;
        float b = (seal / (255 * 255)) % 255;
        hash = GLKVector3Make(r/255, g/255, b/255);
    
        return hash;
    }
    

    And the view controller code where you get the pixel from the touch position and get the selected seal from the selected color :

    -(uint)getSealByColor:(GLKVector3)color
    {
        color = GLKVector3DivideScalar(color, 255);
        for (MyObject *o in _objects) {
            if(GLKVector3AllEqualToVector3(o.color, color))
            {
                return o.seal;
            }
        }
        return 0;
    }
    
    -(void)tap:(UITapGestureRecognizer*)recognizer
    {
        CGPoint p = [recognizer locationInView:self.view];
        GLKVector3 i = [self pickingAt:p];
        _sealSelected = [self getSealByColor:i];
    }
    
    -(GLKVector3)pickingAt:(CGPoint)position
    {
        CGFloat scale = [UIScreen mainScreen].scale;
    
        GLsizei w = self.view.bounds.size.width * scale;
        GLsizei h = self.view.bounds.size.height * scale;
    
        GLuint fb;
        GLuint rb;
        GLuint db;
    
        Byte pixelColor[4] = {0,};
    
        glGenFramebuffers(1, &fb);
        glBindFramebuffer(GL_FRAMEBUFFER, fb);
        glGenRenderbuffers(1, &rb);
        glBindRenderbuffer(GL_RENDERBUFFER, rb);
    
        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, w, h);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, rb);
    
        //here we also create a depth buffer for 3D objects picking
        glGenRenderbuffers(1, &db);
        glBindRenderbuffer(GL_RENDERBUFFER, db);
    
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, w, h);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, db);
    
        GLenum status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
        if (status != GL_FRAMEBUFFER_COMPLETE) {
            NSLog(@"Framebuffer status: %x", (int)status);
            return GLKVector3Make(0.0, 0.0, 0.0);
        }
    
        //we render the scene with our picking boolean activated
        [self render:YES];
    
        glReadPixels(position.x * scale, (h - (position.y * scale)), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixelColor);
    
        glDeleteRenderbuffers(1, &db);
        glDeleteRenderbuffers(1, &rb);
        glDeleteFramebuffers(1, &fb);
    
        return GLKVector3Make(pixelColor[0], pixelColor[1], pixelColor[2]);
    }
    

    Hope this help someone, this is how i do to allow color picking for more than 255 objects.

提交回复
热议问题