opengl glkit color-picking glreadpixels总是返回零色像素(0,0,0)

时间:2013-09-30 21:49:41

标签: ios opengl-es opengl-es-2.0 glkit ray-picking

以下代码可以是使用glkit进行颜色挑选的完整模板。我只需要理解为什么屏幕外缓冲区中的所有像素都被着色(0,0,0),如下面打印到nslog。 注意:顶点数组在头文件中定义为const数组,它在我项目的另一部分的屏幕上很好地显示(我的问题在于屏幕外)。

标题文件:

typedef struct {
    float Position[3];
    float Color[4];
    float TexCoord[2]; 
    float Normal[3]; 
} Vertex;

//Vertices array format: {{vertex.x, vertex.y, vertex.z}, {color.R, color.G, color.B, color.alpha}, {texture.U, texture.V}, {normal.x, normal.y, normal.z}},
const Vertex parparit51OBJVertices[] = {
   {{0.057, -0.088, -0.155},{1,1,1,1},{0.848, 0.810}, {0.329, -0.157, -0.931}},
   {{0.056, -0.035, -0.165},{1,1,1,1},{0.848, 0.811}, {0.338, -0.139, -0.931}}, ......

在viewController代码中:

GLuint _pickFBO = 0;
int32_t glVertexAttributeBufferID = 0;

- (IBAction) tapGesture:(id)sender
{
    if ([(UITapGestureRecognizer *)sender state] == UIGestureRecognizerStateEnded) {

        NSLog( @"In tap ended" );

        CGPoint tapLocation = [(UITapGestureRecognizer *)sender locationInView:self.view];

       int tt = [self findMeshByPoint:tapLocation];
    }
}

- (NSUInteger)findMeshByPoint:(CGPoint)point
{
    //In openGL the y axis starts from the bottom of the screen
    point.y = self.view.bounds.size.height - point.y;

    GLKView *glView = (GLKView *)self.view;
    NSAssert([glView isKindOfClass:[GLKView class]],
             @"View controller's view is not a GLKView");

    // Make the view's context current
    [EAGLContext setCurrentContext:glView.context];

    _height = ((GLKView *)self.view).drawableHeight;
    _width = ((GLKView *)self.view).drawableWidth;

    self.effect.useConstantColor = GL_TRUE;
    self.effect.colorMaterialEnabled = GL_TRUE;
    self.effect.light0.diffuseColor = GLKVector4Make(1.0f,1.0f,1.0f,1.0f);

    glBindVertexArrayOES(0);

        glDisable(GL_DITHER);
        glEnable(GL_DEPTH_TEST);
        glLineWidth(2.0F);

       // Important to turn light off !!!
        self.effect.light0.enabled = GL_TRUE;

        glDisableVertexAttribArray(GLKVertexAttribTexCoord0);

    //this crashes the code
    //glEnableVertexAttribArray(GLKVertexAttribColor);

        self.effect.constantColor = GLKVector4Make( 0.0f,  //This should be meshId/255.0f
                                                   0.8f, 0.8f, 1.0f);

    if(0 == _glVertexAttributeBufferID)
    {
        GLuint  glName;

        glGenBuffers(1,                // STEP 1
                     &glName);
        glBindBuffer(GL_ARRAY_BUFFER,  // STEP 2
                     glName);
        glBufferData(                  // STEP 3
                     GL_ARRAY_BUFFER,  // Initialize buffer contents
                     sizeof(parparit51OBJVertices), parparit51OBJVertices,
                     GL_STATIC_DRAW);            // Hint: cache in GPU memory

        _glVertexAttributeBufferID = glName;

        GLenum err = glGetError();
        if (err != GL_NO_ERROR) {
            NSLog(@"Error creating buffer %i. glError: 0x%04X", glName, err);
        }
    }
    else
    {
        glBindBuffer(GL_ARRAY_BUFFER,
                     _glVertexAttributeBufferID);
    }

     [self buildFBO];

    glBindFramebuffer(GL_FRAMEBUFFER, _pickFBO);
    //glViewport(0, 0, _width, _height);

    //???
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 12 * sizeof(GLfloat), 0);
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE,  12 * sizeof(GLfloat), (GLvoid*) (sizeof(float) * 9));

    GLKMatrix4 modelViewMatrixForParparit = GLKMatrix4MakeTranslation(0.0f, 0.3f, -3.5f );
    modelViewMatrixForParparit = GLKMatrix4Scale(modelViewMatrixForParparit, 1.0, 1.0, 1.0);
    self.effect.transform.modelviewMatrix = modelViewMatrixForParparit;

    self.effect.constantColor = GLKVector4Make( 0.8f, 0.3f, 0.3f, 1.0f );

    [self.effect prepareToDraw];
    glDrawArrays(GL_TRIANGLES, 0, sizeof(parparit51OBJVertices) / sizeof(Vertex));

    const GLfloat width = [glView drawableWidth];
    const GLfloat height = [glView drawableHeight];
    NSAssert(0 < width && 0 < height, @"Invalid drawble size");


    int blackPixelsCounter = 0;
    int coloredPixelsCounter = 0;
    GLubyte savePixelColor[4] = {0, };
    bool bFoundDifferentColors = NO;

    GLubyte pixelColor[4];  // Red, Green, Blue, Alpha color

    glReadPixels(50,
                 50,
                 1,
                 1,
                 GL_RGBA,
                 GL_UNSIGNED_BYTE,
                 pixelColor);

    //#ifdef DEBUG
    {  // Report any errors
        GLenum error = glGetError();
        if(GL_NO_ERROR != error)
        {
            NSLog(@"GL Error: 0x%x", error);
        }
    }
    //#endif

    savePixelColor[0] = pixelColor[0];
    savePixelColor[1] = pixelColor[1];
    savePixelColor[2] = pixelColor[2];

    for (GLint xx=0; xx<_width; xx++) {
        for (GLint yy=0; yy<_height; yy++) {

            glReadPixels(xx,
                         yy,
                         1,
                         1,
                         GL_RGBA,
                         GL_UNSIGNED_BYTE,
                         pixelColor);

            //#ifdef DEBUG
            {  // Report any errors
                GLenum error = glGetError();
                if(GL_NO_ERROR != error)
                {
                    NSLog(@"GL Error: 0x%x", error);
                }
            }
            //#endif

            if ( (savePixelColor[0] != pixelColor[0]) || (savePixelColor[1] != pixelColor[1]) || (savePixelColor[2] != pixelColor[2]) )
            {
               bFoundDifferentColors = YES;
            }

            if ( (pixelColor[0] !=0) || (pixelColor[1] !=0) || (pixelColor[2] !=0) )  {
                //NSLog(@"pixelColor[0]=%i, pixelColor[1]=%i, pixelColor[2]=%i", pixelColor[0], pixelColor[1], pixelColor[2] );


                coloredPixelsCounter++;
            }
            else
            {
                blackPixelsCounter++;
            }
        }
     }

     NSLog( @"colored pixels=%i  black pixels=%i", coloredPixelsCounter, blackPixelsCounter );
     if ( bFoundDifferentColors )
     {
         NSLog( @"Found at least 2 different pixels colors in picking buffer !" );
     }
    else
    {
        NSLog( @"All pixels have the same color: %i, %i, %i",  savePixelColor[0], savePixelColor[1], savePixelColor[2]);
    }

    NSLog( @"******* 9" );


    //--- at the end !!! -------

    // Restore OpenGL state that pickTerrainEffect changed
    glBindFramebuffer(GL_FRAMEBUFFER, 0); // default frame buffer
    //glViewport(0, 0, _width, _height); // full area of glView

//#ifdef DEBUG
    {  // Report any errors
        GLenum error = glGetError();
        if(GL_NO_ERROR != error)
        {
            NSLog(@"GL Error: 0x%x", error);
        }
    }
//#endif

    NSLog( @"******* 10" );


    return 0;

}


//tap-11
-(void) buildFBO
{
    NSLog(@"before: buildFBO._pickFBO=%i", _pickFBO );

    if ( 0 == _pickFBO )
    {

        NSLog(@"buildFBO._pickFBO=%i", _pickFBO );

        GLuint colorRenderbuffer;
        //GLuint framebuffer;

        glGenFramebuffers(1, &_pickFBO);
        glBindFramebuffer(GL_FRAMEBUFFER, _pickFBO);

        glGenRenderbuffers(1, &colorRenderbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, colorRenderbuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8_OES, _width, _height);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_OES, GL_RENDERBUFFER,  colorRenderbuffer);

        GLuint depthRenderbuffer;
        glGenRenderbuffers(1, &depthRenderbuffer);
        glBindRenderbuffer(GL_RENDERBUFFER, depthRenderbuffer);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, _width, _height);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRenderbuffer);

        if(glCheckFramebufferStatus(GL_FRAMEBUFFER) !=
           GL_FRAMEBUFFER_COMPLETE)
        {
            NSLog(@"failed to make complete framebuffer object %x", glCheckFramebufferStatus(GL_FRAMEBUFFER));
            //+++tbd+++UtilityPickTerrainEffectDestroyFBO(fboName);
            return;
        }

        //#ifdef DEBUG
        //    {  // Report any errors
        GLenum error = glGetError();
        if(GL_NO_ERROR != error)
        {
            NSLog(@"GL Error: 0x%x", error);
        }
        //    }
        //#endif
    }
}

1 个答案:

答案 0 :(得分:0)

我认为你需要在读取之前关闭纹理。我的颜色选择器实现工作正常。但我记得大约2天我也只得到0,0,0,0。

这是你的线索。你得到的像素是(0,0,0,0)还是(0,0,0,1)?因为你只提到它是(0,0,0)。由于你有一个clearColor到(0,0,0,1),如果你得到一个零的alpha,它根本就不会读取缓冲区。

我建议分2步完成。一种绘制颜色选择器的方法。另一个从中读取。这是我读取颜色缓冲区的确切代码:

-(void)process3DTouch
{    
  if (colorPickerNeedsRedrawn) {
    [self drawColorPicker];
  }
  glBindFramebuffer(GL_FRAMEBUFFER, pickerFramebuffer);  // speed note - will bind twice if we just had to draw it
  glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, textureInfo[TEX_PICKER].texture, 0);

  Byte pixelColor[4] = {0,0,0,0};
  glReadPixels(colorPickerTouchPosition.x * backingScale, (backingHeight - (colorPickerTouchPosition.y * backingScale)), 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixelColor);
  ColorSpec pickerColor = ColorSpecMake((float)pixelColor[0]/255, (float)pixelColor[1]/255, (float)pixelColor[2]/255, (float)pixelColor[3]/255);

  //NSLog(@"what is pixelColor at %f,%f = %f %f %f %f", colorPickerTouchPosition.x, colorPickerTouchPosition.y, pickerColor.r,pickerColor.g,pickerColor.b,pickerColor.a);

  if (pickerColor.a == 0.0) {
    whatTouched=TOUCHED_NOTHING;
    whatSecondaryTouched=TOUCHED_NOTHING;
    NSLog(@"touched nothing");
    processColorPicker=false;
    return;
  }
  // now look up the item index from the color
  int itemIndex = [self itemIndexFromColor:pickerColor];

  [self handleTouchedItem: itemIndex];

  processColorPicker=false;
}

颜色选择器的另一个好的调试方法是绘制颜色选择器,然后将颜色选择器纹理绘制到屏幕上,这样你就可以看到在选择器的图形中是否还有其他东西。