OpenGL ES无法正常工作

时间:2012-12-30 23:33:13

标签: iphone objective-c opengl-es

我有一个GLKView,几乎可以显示我想要的形状,但有些东西仍然无法正常工作。

      3_______________________2
      |\                     /|
      | \_ _ _ _ _ _ _ _ _ _/ |
      | /4                 5\ |
      |/_____________________\|
      0                       1
  • 纹理映射正在正面工作,其他两个面孔确实不起作用,三角形缺少

  • 当我使用颜色时,脸部看起来似乎符合要求,但背面不会在由点4和5形成的边缘处连接(请看我提供的图纸上文)。
    我想(如果你从侧面看)这三个面形成一个等边三角形。

我已暂时注释掉代码的纹理映射部分,以便您可以测试它。

在这里我设置了我的视图(注意我的视图的尺寸。坐标系工作正常,没有摆弄低值。面部看起来很好,他们只是没有,正如我所说的那样在后面加入):

    EAGLContext * context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
    OpenGLShape *view = [[OpenGLShape alloc] initWithFrame:CGRectMake(0, 200, 320, 80) context:context];
    view.delegate = view;
    [view setupGL];
    [self.view addSubview:view];

- (void)setupGL {

    [EAGLContext setCurrentContext:self.myContext];

    //glEnable(GL_CULL_FACE);


    self.effect = [[GLKBaseEffect alloc] init];

    BOOL useTexture = NO;

    // Create default framebuffer object.
    glGenFramebuffers(1, &defaultFrameBuffer);
    glBindFramebuffer(GL_FRAMEBUFFER, defaultFrameBuffer);

    if(useTexture){
        NSDictionary * options = [NSDictionary dictionaryWithObjectsAndKeys:
                              [NSNumber numberWithBool:YES],
                              GLKTextureLoaderOriginBottomLeft,
                              nil];

        NSError * error;
        NSString *path = [[NSBundle mainBundle] pathForResource:@"blogcell@2x" ofType:@"png"];
        GLKTextureInfo * info = [GLKTextureLoader textureWithContentsOfFile:path options:options error:&error];
        if (info == nil) {
            NSLog(@"Error loading file: %@", [error localizedDescription]);
        }
        self.effect.texture2d0.name = info.name;
        self.effect.texture2d0.enabled = true;

        glGenBuffers(1, &texArray);
        glBindBuffer(GL_ARRAY_BUFFER, texArray);
        glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
        glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, 0,0);
        glBufferData(GL_ARRAY_BUFFER, sizeof(TexCoords), TexCoords, GL_STATIC_DRAW);


    }else{

        glGenBuffers(1, &colArray);
        glBindBuffer(GL_ARRAY_BUFFER, colArray);
        glEnableVertexAttribArray(GLKVertexAttribColor);
        glVertexAttribPointer(GLKVertexAttribColor, 4, GL_FLOAT, GL_FALSE, 0, 0);
        glBufferData(GL_ARRAY_BUFFER, sizeof(Color), Color, GL_STATIC_DRAW);
    }

    glGenRenderbuffers(1, &depthBuffer);
    glBindRenderbuffer(GL_RENDERBUFFER, depthBuffer);
    glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, 320.0f, 80.0f);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthBuffer);

    glEnable(GL_DEPTH_TEST);

    glGenBuffers(1, &vertexArray);
    glBindBuffer(GL_ARRAY_BUFFER, vertexArray);
    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition,3,GL_FLOAT,GL_FALSE,0,0);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);




    self.effect.transform.projectionMatrix = GLKMatrix4MakePerspective(51.4f,4.0f, 0.1f, 10.75f);
   rotMatrix = GLKMatrix4Translate(self.effect.transform.modelviewMatrix,0, 0, -3);


}




- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {

    self.opaque = NO;
    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    [self.effect prepareToDraw];

    glDrawArrays(GL_TRIANGLES, 0, sizeof(Vertices));
}

红色=正面(由点0123组成)

蓝色=背面(顶部 - 由积分4523组成)

绿色=背面(底部 - 由点0154组成)

白色=背景

为了看看它们是否混合/剔除等,我还使面部半透明(alpha = 0.5)。

Initial state (no rotation)

Slight rotation around x-axis

Almost full rotation around x-axis

2 个答案:

答案 0 :(得分:10)

在OpenGL中,相机始终位于{0,0,0},更改位置的是3D世界。

对于正交投影,投影矩阵由下式给出:

self.effect.transform.projectionMatrix = GLKMatrix4MakeOrtho(left, right, bottom, top, front, back);

enter image description here

正交投影中的物体在靠近或远离相机时看起来大小相同。

透视投影中的物体在远离相机时看起来较小。

enter image description here

对于透视投影,投影矩阵由下式给出:

self.effect.transform.projectionMatrix = GLKMatrix4 GLKMatrix4MakePerspective (fov, aspect, front, back);
);

对于透视投影,视野(fov)的工作方式类似于真实相机上的视野,对于较小的值,视角几乎不可察觉,对于较大的值,由于透视投影引起的失真很大。 / p>

fov角度以弧度为单位,可以调整直到场景适合您的应用

aspect是水平和垂直查看区域之间的屏幕宽高比。

出于实际原因,fov以度为单位指定,因此可以使用如下

GLKMatrix4MakePerspective(fov * M_PI / 180.0f,
                                          screenWidth / screenHeight,
                                          front, back);

在透视投影中,近剪裁平面需要大于零,因此您需要向模型视图矩阵添加一个平移,将世界与camara分开一点。

此转换在模型视图矩阵中指定

self.effect.transform.modelviewMatrix = GLKMatrix4MakeTranslation(0, 0, -frontClippingPlane);

<强>更新

剪裁体积需要包括所有顶点以避免z-fighting与前剪裁平面,在这种情况下,透视投影中的最终平移需要更进一步

self.effect.transform.modelviewMatrix = GLKMatrix4MakeTranslation(0, 0, -frontClippingPlane - 0.1f);

要旋转模型并将其转换到最终位置,您需要将两个变换组合如下:

GLKMatrix4 rotation = GLKMatrix4MakeRotation(angle*M_PI/180, 1, 0, 0); // angle in degrees and x,y, and z coordinates for the rotation axis
GLKMatrix4 translation = GLKMatrix4MakeTranslation( 0, 0, -front - 0.1f);
self.effect.transform.modelviewMatrix = GLKMatrix4Multiply(rotation, translation); // the order matters

以下是OpenGL的旋转轴和方向,即right-handed

enter image description here

这是最终效果

enter image description here

答案 1 :(得分:0)

您的数据是否正确?我没看到Vertices数组是如何填充的。

如果你的数据是你列出的那样,你的顶点上的绕组可能是个问题,例如红色正面0123 就是这个顺序。

默认绕组通常是CCW,你已经将你的rects描述为逆时针,需要正确分解为GL_TRIANGLES:例如0123使013和123。

但是如果您的图表是正确的,那么其他图表面朝外,红色矩形将面向进入由3个矩形边形成的三角形棱柱。

要查看我的意思是将一张纸折叠成2个水平折叠以形成三角形棱镜,沿着连接将其粘贴,并对顶点进行编号。

如果在进入“纹理模式”时只为前脸定义了纹理,则可能会丢失该面部。