做好事并帮助某人(我)摆脱痛苦,因为马上就要跨年了。我正在开发一个 iOS 应用程序,一本 child 图画书,我之前没有偶然发现 OpenGL(更准确地说是 OpenGLES 2.0),所以很有可能我的代码中没有真正得到一些东西。

其中一项任务是不要让画笔溢出用户开始绘制的轮廓。

ios - OpenGL ES 2.0 iOS - 在模板缓冲区中绘制一个矩形并仅在其中限制绘制-LMLPHP

在阅读并理解了一些 OpenGL 基础知识后,我发现使用模板缓冲区是正确的解决方案。这是我的模板缓冲区设置:

glClearStencil(0);

//clear the stencil
glClear(GL_STENCIL_BUFFER_BIT);

//disable writing to color buffer
glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE );

//disable depth buffer
glDisable(GL_DEPTH_TEST);

//enable writing to stencil buffer
glEnable(GL_STENCIL_TEST);

glStencilFunc(GL_NEVER, 1, 0xFF);

glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);

[self drawStencil];

//re-enable color buffer
glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE );

//only draw where there is a 1
glStencilFunc(GL_EQUAL, 1, 1);

//keep the pixels in the stencil buffer
glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );

现在,我只是想在模板缓冲区中绘制一个正方形,看看是否可以将我的绘图限制在该正方形内。这是绘制正方形的方法:
- (void)drawStencil
{
// Create a renderbuffer
GLuint renderbuffer;
glGenRenderbuffers(1, &renderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, renderbuffer);
[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];

// Create a framebuffer
GLuint framebuffer;
glGenFramebuffers(1, &framebuffer);
glBindFramebuffer(GL_FRAMEBUFFER, framebuffer);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, renderbuffer);

// Clear
glClearColor(1, 1, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);

// Read vertex shader source
NSString *vertexShaderSource = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"VertexShader" ofType:@"vsh"] encoding:NSUTF8StringEncoding error:nil];
const char *vertexShaderSourceCString = [vertexShaderSource cStringUsingEncoding:NSUTF8StringEncoding];

// Create and compile vertex shader
GLuint _vertexShader = glCreateShader(GL_VERTEX_SHADER);
glShaderSource(_vertexShader, 1, &vertexShaderSourceCString, NULL);
glCompileShader(_vertexShader);

// Read fragment shader source
NSString *fragmentShaderSource = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"FragmentShader" ofType:@"fsh"] encoding:NSUTF8StringEncoding error:nil];
const char *fragmentShaderSourceCString = [fragmentShaderSource cStringUsingEncoding:NSUTF8StringEncoding];

// Create and compile fragment shader
GLuint _fragmentShader = glCreateShader(GL_FRAGMENT_SHADER);
glShaderSource(_fragmentShader, 1, &fragmentShaderSourceCString, NULL);
glCompileShader(_fragmentShader);

// Create and link program
GLuint program = glCreateProgram();
glAttachShader(program, _vertexShader);
glAttachShader(program, _fragmentShader);
glLinkProgram(program);

// Use program
glUseProgram(program);

// Define geometry
GLfloat square[] = {
    -0.5, -0.5,
    0.5, -0.5,
    -0.5, 0.5,
    0.5, 0.5};

//Send geometry to vertex shader
const char *aPositionCString = [@"a_position" cStringUsingEncoding:NSUTF8StringEncoding];
GLuint aPosition = glGetAttribLocation(program, aPositionCString);
glVertexAttribPointer(aPosition, 2, GL_FLOAT, GL_FALSE, 0, square);
glEnableVertexAttribArray(aPosition);

// Draw
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);

// Present renderbuffer
[context presentRenderbuffer:GL_RENDERBUFFER];
}

这么多代码,什么也没发生……我可以在任何我想要的地方无情地画画,而没有一个模板测试阻止我。

我能做什么?如何检查模板缓冲区内是否绘制了一些东西? 如果你们中有人遗漏了谜题,我很乐意分享代码的任何其他部分。

任何帮助是极大的赞赏!这已经折磨了我一段时间了。我将永远欠你的债!

更新

我让轮廓工作,但我没有使用模板缓冲区。我为每个绘图区域创建了蒙版,并为我在片段着色器中加载的每个蒙版以及画笔纹理创建了纹理。当我点击一个区域时,我会遍历蒙版数组并查看选择了哪个并绑定(bind)蒙版纹理。我会用更合适的标题在 SO 上发表另一篇文章并在那里解释。

最佳答案

分配渲染缓冲区存储的方式看起来有问题:

[context renderbufferStorage:GL_RENDERBUFFER fromDrawable:(CAEAGLLayer*)self.layer];

documentation 提到了这个方法:



我理解它的方式,因为你的“可绘制对象”通常是一个颜色缓冲区,这将创建一个颜色渲染缓冲区。但是在您的情况下,您需要一个带有模板格式的渲染缓冲区。我不确定是否有办法使用上下文类中的实用程序方法来执行此操作(文档中提到了“覆盖内部颜色缓冲区格式”),但最简单的方法可能是直接调用相应的 OpenGL 函数:
glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, width, height);

如果您想使用您自己的 FBO 进行此渲染,您还需要为其创建一个颜色缓冲区,并将其附加到 FBO。否则你不会真正产生任何渲染输出。

与创建新的 FBO 不同,确保默认帧缓冲区具有模板缓冲区并直接渲染到它可能更容易。为此,您可以通过在设置期间进行此调用来为 GLKView 派生 View 请求模板缓冲区:
[view setDrawableStencilFormat: GLKViewDrawableStencilFormat8];

关于ios - OpenGL ES 2.0 iOS - 在模板缓冲区中绘制一个矩形并仅在其中限制绘制,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/34499981/

10-14 22:15