为什么我的OpenGL ES 2.0程序只画了一条线而不是一组线?(GLKit或OpenGL)

3

好的,我已经反复检查过了,迄今为止,我“认为”我理解了OpenGL如何绘制以及如何指定我想要绘制的内容,但是我似乎只能绘制一条线。

使用Xcode 4.2中的模板,我可以得到以下代码。它使用GLKIT绘制我的正方形框架,因为我暂时忽略了opengl es 2.0方法以不使用着色器,但当我触摸屏幕时,它应该绘制我的数组,但它没有……

首先是正方形格式(仅显示模板中使用的变量类型)

GLfloat gCubeVertexData[216] = 
{
    // Data layout for each line below is:
    // positionX, positionY, positionZ,     normalX, normalY, normalZ,
    0.5f, -0.5f, -0.5f,        1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, -0.5f,         1.0f, 0.0f, 0.0f,
    0.5f, -0.5f, 0.5f,         1.0f, 0.0f, 0.0f,
    0.5f, -0.5f, 0.5f,         1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, 0.5f,          1.0f, 0.0f, 0.0f,
    0.5f, 0.5f, -0.5f,         1.0f, 0.0f, 0.0f,

    0.5f, 0.5f, -0.5f,         0.0f, 1.0f, 0.0f,
    -0.5f, 0.5f, -0.5f,        0.0f, 1.0f, 0.0f,
    0.5f, 0.5f, 0.5f,          0.0f, 1.0f, 0.0f,
    0.5f, 0.5f, 0.5f,          0.0f, 1.0f, 0.0f,
    -0.5f, 0.5f, -0.5f,        0.0f, 1.0f, 0.0f,
    -0.5f, 0.5f, 0.5f,         0.0f, 1.0f, 0.0f,

    -0.5f, 0.5f, -0.5f,        -1.0f, 0.0f, 0.0f,
    -0.5f, -0.5f, -0.5f,       -1.0f, 0.0f, 0.0f,
    -0.5f, 0.5f, 0.5f,         -1.0f, 0.0f, 0.0f,
    -0.5f, 0.5f, 0.5f,         -1.0f, 0.0f, 0.0f,
    -0.5f, -0.5f, -0.5f,       -1.0f, 0.0f, 0.0f,
    -0.5f, -0.5f, 0.5f,        -1.0f, 0.0f, 0.0f,

    -0.5f, -0.5f, -0.5f,       0.0f, -1.0f, 0.0f,
    0.5f, -0.5f, -0.5f,        0.0f, -1.0f, 0.0f,
    -0.5f, -0.5f, 0.5f,        0.0f, -1.0f, 0.0f,
    -0.5f, -0.5f, 0.5f,        0.0f, -1.0f, 0.0f,
    0.5f, -0.5f, -0.5f,        0.0f, -1.0f, 0.0f,
    0.5f, -0.5f, 0.5f,         0.0f, -1.0f, 0.0f,

    0.5f, 0.5f, 0.5f,          0.0f, 0.0f, 1.0f,
    -0.5f, 0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    0.5f, -0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    0.5f, -0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    -0.5f, 0.5f, 0.5f,         0.0f, 0.0f, 1.0f,
    -0.5f, -0.5f, 0.5f,        0.0f, 0.0f, 1.0f,

    0.5f, -0.5f, -0.5f,        0.0f, 0.0f, -1.0f,
    -0.5f, -0.5f, -0.5f,       0.0f, 0.0f, -.0f,
    0.5f, 0.5f, -0.5f,         0.0f, 0.0f, -1.0f,
    0.5f, 0.5f, -0.5f,         0.0f, 0.0f, -1.0f,
    -0.5f, -0.5f, -0.5f,       0.0f, 0.0f, -1.0f,
    -0.5f, 0.5f, -0.5f,        0.0f, 0.0f, -1.0f
};

这是我的SetupGL函数,我在“View did Load”函数中只调用一次。

- (void)setupGL
{
    [EAGLContext setCurrentContext:self.context];

    [self loadShaders];

    self.effect = [[GLKBaseEffect alloc] init];
    self.effect.light0.enabled = GL_TRUE; //No Idea why it wont work without this


    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBufferData(GL_ARRAY_BUFFER, sizeof(gCubeVertexData), gCubeVertexData, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, 24, BUFFER_OFFSET(0));

    glBindVertexArrayOES(0);
}

这是更新方法(只是使物体旋转)
- (void)update
{
    float aspect = fabsf(self.view.bounds.size.width / self.view.bounds.size.height);
    GLKMatrix4 projectionMatrix = GLKMatrix4MakePerspective(GLKMathDegreesToRadians(65.0f), aspect, 0.1f, 10000.0f);

    self.effect.transform.projectionMatrix = projectionMatrix;

    GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -10.0f);
    baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f);

    // Compute the model view matrix for the object rendered with GLKit
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -1.5f);
    modelViewMatrix = GLKMatrix4Rotate(modelViewMatrix, _rotation, 1.0f, 1.0f, 1.0f);
    modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);

    self.effect.transform.modelviewMatrix = modelViewMatrix;

    _rotation += self.timeSinceLastUpdate * 0.5f;
}

Draw In Rect方法(我认为是渲染)

- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glBindVertexArrayOES(_vertexArray);

    // Render the object with GLKit
    [self.effect prepareToDraw];

    glDrawArrays(GL_LINE_STRIP, 0, 36); //Probably have to change the 36

}

这是Touch部分:
在触摸开始时,我只是创建NSMutableData。
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{
    UITouch *touch = [touches anyObject];
    startPoint = [touch locationInView:self.view];

    vertexData3 = [NSMutableData dataWithLength: sizeof(GLKVector2)]; //HERE

    if (!referenceAttitude)
        referenceAttitude = motionManager.deviceMotion.attitude;

    writtingON = YES;   

}

在Touches Ended事件中,我正在尝试使用获取到的新顶点进行绘制。这些顶点是使用定时器触发运动管理器读取并进行一些数学计算得出的,加上用户触摸屏幕的位置,因此值应该在屏幕坐标范围内。
然而,为了测试绘图效果,我只是手动创建了一个临时的NSMutableData变量,并添加了一些值(添加方式很糟糕)。我使用NSMutableData是因为另一个教程中建议这样做。我有90%的把握它正确地保存了数据,因为当我检索它时,它确实存在。(http://games.ianterrell.com/how-to-draw-2d-shapes-with-glkit/
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event 
{


    ////////Test array


    tempVert = GLKVector2Make(10, -8);
    NSRange r = {0*sizeof(GLKVector2), sizeof(GLKVector2)};
    [vertexData3 replaceBytesInRange: r withBytes:&tempVert];
    [vertexData3 increaseLengthBy:sizeof(GLKVector2)];

    tempVert = GLKVector2Make(2, -8);
    NSRange q = {1*sizeof(GLKVector2), sizeof(GLKVector2)};
    [vertexData3 replaceBytesInRange: q withBytes:&tempVert];
    [vertexData3 increaseLengthBy:sizeof(GLKVector2)];

    tempVert = GLKVector2Make(4, 9);
    NSRange w = {2*sizeof(GLKVector2), sizeof(GLKVector2)};
    [vertexData3 replaceBytesInRange: w withBytes:&tempVert];
    [vertexData3 increaseLengthBy:sizeof(GLKVector2)];

    tempVert = GLKVector2Make(1, -9);
    NSRange e = {3*sizeof(GLKVector2), sizeof(GLKVector2)};
    [vertexData3 replaceBytesInRange: e withBytes:&tempVert];
    [vertexData3 increaseLengthBy:sizeof(GLKVector2)];

    tempVert = GLKVector2Make(2, -2);
    NSRange t = {4*sizeof(GLKVector2), sizeof(GLKVector2)};
    [vertexData3 replaceBytesInRange: t withBytes:&tempVert];
    [vertexData3 increaseLengthBy:sizeof(GLKVector2)];


    //////////////////////

    glGenVertexArraysOES(1, &_vertexArray);
    glBindVertexArrayOES(_vertexArray);

    glGenBuffers(1, &_vertexBuffer);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);

    glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData3), [vertexData3 mutableBytes], GL_DYNAMIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));

    glBindVertexArrayOES(0);

}

这最后一部分让我疯狂!!!我认为它应该修改缓冲区,使用自己的数组,以便自动更新绘制它。
任何建议都将不胜感激。
谢谢。
哦,如果有人知道如何设置正交矩阵,因为我现在只对2D组件感兴趣,所以我可以用它替换透视矩阵。
编辑:
好吧,我刚试过发送一个随机的GLfloat数组,它确实改变了形状,但为什么不能使用我的NSMutableData数组呢?我认为我正在做与教程中完全相同的过程....
1个回答

0

最后一部分应该只有:

glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexData3), [vertexData3 mutableBytes], GL_DYNAMIC_DRAW);
// bind buffer and specify it's new data (no need to glGenBuffers(), that was done in setupGL())
// also, it would be handy to save number of vertices so it could be used later for drawing (nVertices = sizeof(vertexData3) / sizeof(GLKVector2))

glBindVertexArrayOES(_vertexArray);
glEnableVertexAttribArray(GLKVertexAttribPosition);
glVertexAttribPointer(GLKVertexAttribPosition, 2, GL_FLOAT, GL_FALSE, 0, BUFFER_OFFSET(0));
glBindVertexArrayOES(0);
// bind vertex array and setup the vertex attribute (although this could be done only once, in setupGL())

这样做可以减少OpenGL对象的生成,渲染速度应该会更快(而且不会出现内存耗尽的情况)。

否则,渲染似乎还好。但你真的应该使用实际顶点数来进行绘制:

glDrawArrays(GL_LINE_STRIP, 0, nVertices);

在规模方面几乎肯定存在问题(GLfloats和GLKVector2之间不应该有任何区别)。您通过自己的方法生成了一些点,但只绘制了前36个。可能会生成正确的曲线,但您只能看到其开头的一小段,这自然看起来是平坦的。此外,您似乎不确定您的位置计算是否生成窗口内的坐标,也许最好的办法是a)在此处发布您的源代码b)将您的坐标乘以一些小值(但大于零),以便它们适合屏幕。

至于正交投影,您可以使用:

GLKMatrix4MakeOrtho(-1, 1, -1, 1, .1, 1000); // this sets normalized coordinates
GLKMatrix4MakeOrtho(0, widthPx, 0, heightPx, .1, 1000); // this sets pixel coordinates

GLKMatrix4MakeOrtho的参数只是屏幕角落(左,右,底部,顶部)和正在绘制的深度范围(近,远)的期望坐标。
我希望这能给你一些启示...

是的,我有点想通了,但真的不确定问题出在哪里。当我读到你的帖子时,它证实了我只绘制了第一个点,我以为那个数字意味着“对象数量”,比如三角形、线条等,但实际上不是哈哈。另外,你知道如何在运行时创建和加载顶点/纹理吗?如果你知道,请告诉我,这样我就可以发一个问题了。我有点放弃在这里问关于OpenGL的问题了lol。 - Pochi
是的,glDrawArrays()的最后一个参数是顶点数,而不是图元数。至于在运行时创建顶点/纹理,实际上你现在正在创建运行时顶点,所以我不确定还有什么需要知道的(但如果需要,我会提供答案)。关于纹理 - 有许多创建纹理的方法(加载图像、渲染到纹理、程序纹理)...我不知道你想知道什么。如果要创建一个新问题,请具体说明你想要实现的效果。 - the swine

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接