0

在我的应用程序中,我使用 OpenGL ES 渲染从 Internet 下载的文件,然后将其解析为顶点数组,因此我必须在启动后输入顶点和法线数据。我是 OpenGL ES 的新手,但我一直在阅读和学习。我已经设置了一个似乎工作正常的顶点和法线缓冲区,但我认为我将顶点和法线数据错误地放入缓冲区,因为当我加载视图时,那里有一个对象模糊地类似于我想要的形状但是三角形向各个方向偏离,形状的某些部分丢失了。这是我将数据输入缓冲区的代码:

    for (int i = 0; i < triangle_cnt; i++) {
        int base = i * 18;
        GLfloat x1 = vertices[base];
        GLfloat y1 = vertices[base + 1];
        GLfloat z1 = vertices[base + 2];
        GLfloat x2 = vertices[base + 6];
        GLfloat y2 = vertices[base + 7];
        GLfloat z2 = vertices[base + 8];
        GLfloat x3 = vertices[base + 12];
        GLfloat y3 = vertices[base + 13];
        GLfloat z3 = vertices[base + 14];
       
        vector_t normal;
        vector_t U;
        vector_t V;
        GLfloat length;
       
        U.x = x2 - x1;
        U.y = y2 - y1;
        U.z = z2 - z1;
       
        V.x = x3 - x1;
        V.y = y3 - y1;
        V.z = z3 - z1;
       
        normal.x = U.y * V.z - U.z * V.y;
        normal.y = U.z * V.x - U.x * V.z;
        normal.z = U.x * V.y - U.y * V.x;
       
        length = normal.x * normal.x + normal.y * normal.y + normal.z * normal.z;
        length = sqrt(length);
       
        base = i * 9;
        verticesBuff[base] = x1;
        verticesBuff[base + 1] = y1;
        verticesBuff[base + 2] = z1;
       
        normalsBuff[base] = normal.x;
        normalsBuff[base + 1] = normal.y;
        normalsBuff[base + 2] = normal.z;
       
        verticesBuff[base + 3] = x2;
        verticesBuff[base + 4] = y2;
        verticesBuff[base + 5] = z2;
       
        normalsBuff[base + 3] = normal.x;
        normalsBuff[base + 4] = normal.y;
        normalsBuff[base + 5] = normal.z;
       
        verticesBuff[base + 6] = x3;
        verticesBuff[base + 7] = y3;
        verticesBuff[base + 8] = z3;
       
        normalsBuff[base + 6] = normal.x;
        normalsBuff[base + 7] = normal.y;
        normalsBuff[base + 8] = normal.z;

        fprintf(stderr, "%ff, %ff, %ff,          %ff, %ff, %ff, \n", x1, y1, z1, normal.x, normal.y, normal.z);
        fprintf(stderr, "%ff, %ff, %ff,          %ff, %ff, %ff, \n", x2, y2, z2, normal.x, normal.y, normal.z);
        fprintf(stderr, "%ff, %ff, %ff,          %ff, %ff, %ff, \n", x3, y3, z3, normal.x, normal.y, normal.z);
    }

这是我用于使用这些缓冲区的代码:

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

[self loadShaders];

self.effect = [[GLKBaseEffect alloc] init];
self.effect.light0.enabled = GL_TRUE;
self.effect.light0.diffuseColor = GLKVector4Make(.05f, .55f, 1.0f, 1.0f);

glEnable(GL_DEPTH_TEST);

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

glGenBuffers(1, &_vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, vertCount*sizeof(verticesBuff)*3*2, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(verticesBuff) * vertCount * 3, verticesBuff);
glBufferData(GL_ARRAY_BUFFER, vertCount*sizeof(normalsBuff)*3*2, NULL, GL_STATIC_DRAW);
glBufferSubData(GL_ARRAY_BUFFER, sizeof(GLfloat) * vertCount * 3, sizeof(normalsBuff) * vertCount * 3, normalsBuff);

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

glBindVertexArrayOES(0);

_rotMatrix = GLKMatrix4Identity;

_quat = GLKQuaternionMake(0, 0, 0, 1);
_quatStart = GLKQuaternionMake(0, 0, 0, 1);
}
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect {
glClearColor(0.78f, 0.78f, 0.78f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

glBindVertexArrayOES(_vertexArray);

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

glVertexPointer(3, GL_FLOAT, 0, verticesBuff);
glNormalPointer(GL_FLOAT, 0, normalsBuff);

glDrawArrays(GL_TRIANGLES, 0, vertCount); //*******************************

// Render the object again with ES2
glUseProgram(_program);

glUniformMatrix4fv(uniforms[UNIFORM_MODELVIEWPROJECTION_MATRIX], 1, 0, _modelViewProjectionMatrix.m);
glUniformMatrix3fv(uniforms[UNIFORM_NORMAL_MATRIX], 1, 0, _normalMatrix.m);

glDrawArrays(GL_TRIANGLES, 0, vertCount);
}

如果我在创建 OpenGL ES 应用程序时使用 Apple 提供的代码获取这些日志并将它们粘贴到示例应用程序的顶点数组中,那么对象会呈现得很漂亮,所以我推断我一定只是将顶点数据放错了。

那么有人可以帮助我理解输入顶点和法线时我做错了什么吗?任何帮助表示赞赏。

这也是我的渲染的样子:

糟糕的渲染

至少在形状上,它应该是这样的:

很好的渲染

4

1 回答 1

0

这有点混乱,可能会有很多问题。您目前面临的似乎是:

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

步幅参数 (24) 应该sizeof(GLfloat)*3和法线一样。这是因为您不再使用交错的顶点结构,现在您的位置坐标被紧密打包(也就是说您现在也可以0用作步幅参数)。您使用此错误产生的结果是,只有第二个顶点被采用,其他顶点被丢弃,并且当所有位置都被采用时,它开始绘制法线。此外,如果您的正常指针和偏移设置正确,则您正在将它们读取到缓冲区之外,并且应该会产生崩溃或读取其他一些资源。

于 2013-07-16T06:40:39.547 回答