[英]opengl glkit color-picking glreadpixels always returns zero colored pixels (0,0,0)
以下代碼可以是使用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
}
}
我認為您需要先關閉紋理,然后再讀取紋理。 我的顏色選擇器實現工作正常。 但是我記得大約兩天我也只得到0,0,0,0。
這是給你的線索。 您要獲取的像素是(0,0,0,0)還是(0,0,0,1)? 因為您只提到它是(0,0,0)。 由於您將clearColor設置為(0,0,0,1),因此,如果得到的alpha為零,則根本不讀取緩沖區。
我建議分兩個步驟進行。 一種繪制顏色選擇器的方法。 另一個從中讀取。 這是我讀取顏色緩沖區的確切代碼:
-(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;
}
拾色器的另一種不錯的調試方法是先繪制拾色器,然后在屏幕上繪制拾色器紋理,以便您可以看到拾色器中是否還有其他內容。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.