2013-09-30 19 views
0

다음 코드는 glkit으로 색상 피킹을위한 완벽한 템플릿이 될 수 있습니다. 나는 왜 오프 스크린 버퍼에있는 모든 픽셀들이 nslog에 아래에 인쇄 된 것처럼 색깔 (0, 0, 0)인지 이해해야한다. 참고 : 정점 배열은 헤더 파일에서 const 배열로 정의됩니다. 이는 프로젝트의 다른 섹션에서 화면에 잘 표시됩니다 (문제는 오프 스크린과 관련됨).opengl glkit 색상 피킹 glreadpixels은 항상 0 색의 픽셀을 반환합니다. (0,0,0)

헤더 파일 다음의 ViewController 코드에서

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}}, ...... 

:

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 
    } 
} 
+0

왜 외막에 관심이 있습니까? –

+0

예수, 이것은 색 따기라는 이름의 알려진 방법입니다. 우리는 각 메쉬에 대해 고유 한 색으로 오프 스크린 버퍼에 렌더링합니다. 사용자가 화면을 두 드렸을 때 그는 그가 두드린 색깔을 얻습니다. 즉, 메쉬가 화면과 오프 스크린 버퍼 모두에 렌더링됩니다. 화면에서 원래 텍스처로 렌더링하고 오프 스크린 버퍼에 각 메쉬의 고유 한 색상으로 렌더링합니다. – user2492853

+0

정말 잘 모르겠지만 도려내기를 사용하지 않으셨습니까? 당신이 깊이 테스트를하지는 않았지만 도려내는 걸 봤습니다. –

답변

0

은 당신이 그것에서 읽기 전에 질감을 닫을 필요가 있다고 생각합니다. 내 색상 선택기 구현이 잘 작동합니다. 하지만 약 2 일 동안 나는 단지 0,0,0,0만을 얻었음을 기억합니다.

여기 단서가 있습니다. 픽셀이 (0,0,0,0) 또는 (0,0,0,1)입니까? 왜냐하면 당신은 그것이 (0, 0, 0)이라는 것을 언급하기 때문입니다. clearColor가 (0, 0, 0, 1)이기 때문에 0의 알파를 얻으면 버퍼를 전혀 읽지 않습니다.

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; 
} 

또 다른 좋은 디버깅 방법은 색상 선택기를 그리고 당신은 뭔가 다른 것이 있다면 당신이 볼 수 있도록 한 다음 화면에 색상 선택기 텍스처를 그릴 수 있습니다 : 여기 내 정확한 코드는 나의 컬러 버퍼를 읽는입니다 피커 그림에.