【问题标题】:Getting OpenGL stencil buffer clipping working on glkit让 OpenGL 模板缓冲区剪辑在 glkit 上工作
【发布时间】:2014-05-04 20:05:53
【问题描述】:

我试图在 GLKViewController 中重现 this stencil buffer tutorial here 中的效果,其中模板用于剪辑。

在我的 drawinrect 方法中,我有:

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


    [self.effect prepareToDraw];

    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, TexCoord));

    glBindBuffer(GL_ARRAY_BUFFER, _vertexBuffer);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);

    glClearColor(0.5, 0.5, 0.5, 1.0);
    glClear( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);



    glClear(GL_DEPTH_BUFFER_BIT);
    glEnable(GL_STENCIL_TEST);
    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
    glDepthMask(GL_FALSE);
    glStencilFunc(GL_NEVER, 1, 0xFF);
    glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);  // draw 1s on test fail (always)

    // draw stencil pattern
    glStencilMask(0xFF);
    glClear(GL_STENCIL_BUFFER_BIT);  // needs mask=0xFF




    glDrawElements(GL_TRIANGLES, 1*6, GL_UNSIGNED_SHORT, 0);

     glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
    glDepthMask(GL_TRUE);
    glStencilMask(0x00);


    // draw only where stencil's value is 1
    glStencilFunc(GL_EQUAL, 1, 0xFF);


    glDrawElements(GL_TRIANGLES, nLiveSquares*6, GL_UNSIGNED_SHORT, 0);


    glDisable(GL_STENCIL_TEST);

}

顶点缓冲区包含正方形的信息,其中包含纹理。

我想要获得的效果是让第一个正方形用于定义模板形状,然后当我绘制场景时,位于第一个正方形之外的任何内容都会被剪裁。因此,我使用了两次 drawElements - 第一次绘制裁剪正方形,然后绘制所有正方形。

我还有另一种用于 OpenGL 设置的方法,在程序开始时调用一次。正如对this stackoverflow question 的回答所建议的那样,这包括:

GLuint depthStencilRenderbuffer;

glGenRenderbuffers(1, &depthStencilRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, depthStencilRenderbuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthStencilRenderbuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, depthStencilRenderbuffer);

运行此程序只会显示包含灰色透明颜色的屏幕。似乎所有内容都已被印出(或未绘制到屏幕上)。

【问题讨论】:

  • 您是否将您的GLKViewdrawableStencilFormat 设置为合适的值?
  • 我不得不问:为什么要连续两次清除深度缓冲区? glClear ( GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 后跟 glClear (GL_DEPTH_BUFFER_BIT)
  • 这是我的错误。好眼力。谢谢。

标签: ios opengl-es-2.0 glkit


【解决方案1】:

解决办法:

i) 我将初始化更改为:

GLuint depthStencilRenderbuffer;
glBindRenderbufferOES(GL_RENDERBUFFER_OES, depthStencilRenderbuffer);
glRenderbufferStorageOES(GL_RENDERBUFFER_OES,
                         GL_DEPTH24_STENCIL8_OES,
                         self.view.bounds.size.width,
                         self.view.bounds.size.height);

我不确定有什么区别,但这似乎有效。

ii) 在我使用的设置中:

GLKView *view = (GLKView *)self.view;
view.context = self.context;
view.drawableDepthFormat = GLKViewDrawableDepthFormat24;
view.drawableStencilFormat = GLKViewDrawableStencilFormat8;

感谢@rickster 的建议。

【讨论】:

  • 您在前两行代码中使用了未初始化的depthStencilRenderbuffer 变量。您需要在这两行之间添加glGenRenderbuffers(1, &depthStencilRenderbuffer);。您似乎并没有真正在发布的代码中使用渲染缓冲区,所以我不确定您对第一个代码片段的意图是什么。
  • 如果你同时做这两件事,你就是在创建两个深度/模板缓冲区并且只使用一个。只要您绘制到GLKView 提供的默认帧缓冲区(即您没有使用glBindFramebuffer 在其他地方绘制),您应该只需要您的 (ii) 列表。
猜你喜欢
  • 2011-03-09
  • 2011-04-16
  • 2018-06-23
  • 2012-07-11
  • 1970-01-01
  • 2011-08-14
  • 2012-01-13
  • 1970-01-01
相关资源
最近更新 更多