在 Open GL ES 2.0 (iOS GLKit) 中处理多个网格?

发布于 2025-01-02 15:38:35 字数 546 浏览 1 评论 0原文

我已成功使用 iOS 的 GLKit 在 Open GL ES 2.0 中创建单个网格。我不知道如何创建第二个网格,除了位置不同之外,它看起来与第一个网格相同。

我认为最有帮助的是,如果有人可以简单地提供一些绘制多个网格的示例代码,因为我认为我的做法完全错误。尽管如此,这里列出了我为实现这项工作所做的努力。

  • 我创建了两个顶点信息的 C 数组。第一个是我的模板(以 0,0,0 为中心的硬编码坐标),第二个是我想要显示的内容(最初为空)。
  • 我创建了两个索引信息的 C 数组。与顶点信息的处理相同。
  • 我有两个全局变量 int,vertexCount 和 indiceCount,最初都是 0。
  • 我有 ac 函数 createAt(float x, float y, float z)。该函数将我的顶点模板复制到我的顶点显示数组中,然后将传入的偏移量应用到每个顶点。它还复制索引并应用偏移量,以便它们指向新的显示顶点。

但这不起作用。屏幕上仅绘制一个对象。

看看其他人的问题和答案,听起来也许我应该有多个顶点缓冲区?我不知道;我非常困惑。

I've managed to create a single mesh in Open GL ES 2.0 using iOS's GLKit. What I can't figure out is how to create a second mesh that looks identical to the first except with a different position.

I think what would be most helpful would be if someone could simply provide some sample code that draws multiple meshes, as I think I'm going about this entirely wrong. Nonetheless, here's a list of what I've done to try make this work.

  • I created two C-arrays of vertex information. The first is my template (hardcoded coordinates centered at 0,0,0) and the second is what I'd like displayed (initially empty).
  • I created two C-arrays of indice information. Same deal as with the vertex information.
  • I have two global variable ints, vertexCount and indiceCount, both initially 0.
  • I have a c function, createAt(float x, float y, float z). This function copies my vertex template into my vertex display array and then applies the passed in offsets to each vertex. It also copies indices in and applies an offset so that they point at the new display vertexes.

This doesn't work though. Only one object gets drawn on screen.

Looking through other people's questions and answers, it sounds like maybe I should have multiple vertex buffers? I don't know; I'm horribly confused.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

秋日私语 2025-01-09 15:38:35

使用 GLKit 渲染具有相同几何形状但不同位置或方向的多个网格非常容易,这要归功于 GLKBaseEffect 类。看一下 Xcode 提供的“OpenGL Game”模板,它用 GLKit 渲染一个立方体,用 OpenGL ES 2.0 渲染另一个立方体。

下面是 OpenGL 游戏示例的修改,它在两个旋转的立方体上方添加了一个新的立方体:

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

    glBindVertexArrayOES(_vertexArray);

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

    glDrawArrays(GL_TRIANGLES, 0, 36);

    // Render another version of the object with GLKit

    // First put it in a different place (you would normally
    // do this in the update loop):
    GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f);
    baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f);    
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 1.5, -0.0f);
    modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
    self.effect.transform.modelviewMatrix = modelViewMatrix;

    // Now render it:
    [self.effect prepareToDraw];
    glDrawArrays(GL_TRIANGLES, 0, 36);

    // 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, 36);
}

“渲染另一个版本”和“再次渲染对象”注释之间的代码是新的。它需要做的第一件事是为额外的立方体提出一个新的模型视图矩阵;这是基于 update: 中的代码(未显示)。通常我会把代码放在那里,但我想保持示例简短。

接下来它渲染立方体,这对于 GLKit 来说非常简单。 GLKit 耶!

Apple GLKit / OpenGL 游戏示例中三个立方体的屏幕截图

我希望这会有所帮助。听起来你用额外的顶点和索引数组吠叫了错误的树;如果你想渲染不同的几何图形,但你说的是在不同的地方使用相同的模型,这是必要的。这正是 GLKit 的理想选择。

Rendering multiple meshes with the same geometry but different positions or orientations is quite easy with GLKit, thanks to the GLKBaseEffect class. Take a look at the "OpenGL Game" template provided by Xcode, which renders a cube with GLKit and another cube with OpenGL ES 2.0.

Here's a modification of the OpenGL Game sample which adds a new cube above the two spinning ones:

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

    glBindVertexArrayOES(_vertexArray);

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

    glDrawArrays(GL_TRIANGLES, 0, 36);

    // Render another version of the object with GLKit

    // First put it in a different place (you would normally
    // do this in the update loop):
    GLKMatrix4 baseModelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 0.0f, -4.0f);
    baseModelViewMatrix = GLKMatrix4Rotate(baseModelViewMatrix, _rotation, 0.0f, 1.0f, 0.0f);    
    GLKMatrix4 modelViewMatrix = GLKMatrix4MakeTranslation(0.0f, 1.5, -0.0f);
    modelViewMatrix = GLKMatrix4Multiply(baseModelViewMatrix, modelViewMatrix);
    self.effect.transform.modelviewMatrix = modelViewMatrix;

    // Now render it:
    [self.effect prepareToDraw];
    glDrawArrays(GL_TRIANGLES, 0, 36);

    // 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, 36);
}

The code in-between the "Render another version" and "Render the object again" comments is new. The first thing it needs to do is come up with a new modelview matrix for the additional cube; this is based on the code in update: (not shown). Normally I'd put the code up there but I wanted to keep the sample short.

Next it renders the cube, which is pretty simple with GLKit. Yay GLKit!

Screenshot of three cubes in Apple's GLKit / OpenGL Game sample

I hope this helps. It sounds like you're barking up the wrong tree with additional vertex and index arrays; this is necessary if you want to render different geometries, but you said the same model in different places. That's something GLKit is ideal for.

人间不值得 2025-01-09 15:38:35

由于只有 1 个基本效果,我认为您会在更新中进行矩阵计算,然后将其分配给基本效果模型视图矩阵,然后再次绘制?

Since there is only 1 base effect, I take it you would do the matrix calculations in the update, and just assign it to the base effect modelviewmatrix before drawing again?

起风了 2025-01-09 15:38:35

John Riselvato 在上面评论说,他真的希望能够看到更新:方法内容。我真的很希望自己看到这一点,因为在使用相同的 GLKBaseEffect 对象时,我很难将多个对象放在屏幕上。这就是我最终做到的:

// update method where I create 3 different modelViewMatrices to use with my GLKBaseEffect object later in the draw method
- (void)updateWithDeltaTime:(NSTimeInterval)deltaTime
{
    _rotation1 += 120.0 * deltaTime;
    _rotation2 += 150.0 * deltaTime;
    _rotation3 += 180.0 * deltaTime;

    GLKMatrix4 modelViewMatrix = GLKMatrix4Identity;
    modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, -1.0f, 0.0f, -4.0f);
    modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, GLKMathDegreesToRadians(90.0f));
    modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, GLKMathDegreesToRadians(_rotation1));
    _modelViewMatrix1 = modelViewMatrix;

    modelViewMatrix = GLKMatrix4Identity;
    modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 0.0f, 0.0f, -4.0f);
    modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, GLKMathDegreesToRadians(90.0f));
    modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, GLKMathDegreesToRadians(_rotation2));
    _modelViewMatrix2 = modelViewMatrix;

    modelViewMatrix = GLKMatrix4Identity;
    modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 1.0f, 0.0f, -4.0f);
    modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, GLKMathDegreesToRadians(90.0f));
    modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, GLKMathDegreesToRadians(_rotation3));
    _modelViewMatrix3 = modelViewMatrix;
}

// draw method where I re-use my GLKBaseEffect object, applying the 3 modelViewMatrices I set in the update: method above
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    _effect.transform.modelviewMatrix = _modelViewMatrix1;
    [_effect prepareToDraw];
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
    glDrawArrays(GL_TRIANGLES, 0, cylinderVertices);

    _effect.transform.modelviewMatrix = _modelViewMatrix2;
    [_effect prepareToDraw];
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
    glDrawArrays(GL_TRIANGLES, 0, cylinderVertices);

    _effect.transform.modelviewMatrix = _modelViewMatrix3;
    [_effect prepareToDraw];
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer3);
    glDrawArrays(GL_TRIANGLES, 0, cylinderVertices);
}

// how i initially setup my GLKBaseEffect object and my opengl buffers
- (void)_setupGL
{
    [EAGLContext setCurrentContext:_context];
    //glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);

    _effect = [[GLKBaseEffect alloc] init];
    [self _createEffect];
    [_effect prepareToDraw];

    glGenBuffers(1, &_vertexBuffer1);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_vertexBuffer2);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_vertexBuffer3);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer3);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)offsetof(Vertex, Position));
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)offsetof(Vertex, Texel));
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)offsetof(Vertex, Normal));
}

希望这对某人有帮助。

John Riselvato comments above that he really wishes he could see the update: method contents. I really wished to see this myself as I was having difficulty wrapping my head around putting multiple objects on screen, while using the same GLKBaseEffect object. Here's how I finally did it:

// update method where I create 3 different modelViewMatrices to use with my GLKBaseEffect object later in the draw method
- (void)updateWithDeltaTime:(NSTimeInterval)deltaTime
{
    _rotation1 += 120.0 * deltaTime;
    _rotation2 += 150.0 * deltaTime;
    _rotation3 += 180.0 * deltaTime;

    GLKMatrix4 modelViewMatrix = GLKMatrix4Identity;
    modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, -1.0f, 0.0f, -4.0f);
    modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, GLKMathDegreesToRadians(90.0f));
    modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, GLKMathDegreesToRadians(_rotation1));
    _modelViewMatrix1 = modelViewMatrix;

    modelViewMatrix = GLKMatrix4Identity;
    modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 0.0f, 0.0f, -4.0f);
    modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, GLKMathDegreesToRadians(90.0f));
    modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, GLKMathDegreesToRadians(_rotation2));
    _modelViewMatrix2 = modelViewMatrix;

    modelViewMatrix = GLKMatrix4Identity;
    modelViewMatrix = GLKMatrix4Translate(modelViewMatrix, 1.0f, 0.0f, -4.0f);
    modelViewMatrix = GLKMatrix4RotateY(modelViewMatrix, GLKMathDegreesToRadians(90.0f));
    modelViewMatrix = GLKMatrix4RotateZ(modelViewMatrix, GLKMathDegreesToRadians(_rotation3));
    _modelViewMatrix3 = modelViewMatrix;
}

// draw method where I re-use my GLKBaseEffect object, applying the 3 modelViewMatrices I set in the update: method above
- (void)glkView:(GLKView *)view drawInRect:(CGRect)rect
{
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    _effect.transform.modelviewMatrix = _modelViewMatrix1;
    [_effect prepareToDraw];
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
    glDrawArrays(GL_TRIANGLES, 0, cylinderVertices);

    _effect.transform.modelviewMatrix = _modelViewMatrix2;
    [_effect prepareToDraw];
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
    glDrawArrays(GL_TRIANGLES, 0, cylinderVertices);

    _effect.transform.modelviewMatrix = _modelViewMatrix3;
    [_effect prepareToDraw];
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer3);
    glDrawArrays(GL_TRIANGLES, 0, cylinderVertices);
}

// how i initially setup my GLKBaseEffect object and my opengl buffers
- (void)_setupGL
{
    [EAGLContext setCurrentContext:_context];
    //glEnable(GL_CULL_FACE);
    glEnable(GL_DEPTH_TEST);
    glClearColor(0.5f, 0.5f, 0.5f, 1.0f);

    _effect = [[GLKBaseEffect alloc] init];
    [self _createEffect];
    [_effect prepareToDraw];

    glGenBuffers(1, &_vertexBuffer1);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer1);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_vertexBuffer2);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer2);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glGenBuffers(1, &_vertexBuffer3);
    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer3);
    glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);

    glEnableVertexAttribArray(GLKVertexAttribPosition);
    glVertexAttribPointer(GLKVertexAttribPosition, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)offsetof(Vertex, Position));
    glEnableVertexAttribArray(GLKVertexAttribTexCoord0);
    glVertexAttribPointer(GLKVertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)offsetof(Vertex, Texel));
    glEnableVertexAttribArray(GLKVertexAttribNormal);
    glVertexAttribPointer(GLKVertexAttribNormal, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (const GLvoid *)offsetof(Vertex, Normal));
}

Hope this helps someone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文