【发布时间】:2015-01-08 01:09:33
【问题描述】:
我正在使用 OpenGL 中的 2D 图形 - 分形和其他有趣的东西 ^_^。我的基本设置是渲染几个三角形来填充屏幕并使用片段着色器在它们上绘制很酷的东西。我想稍微平滑一下,所以我开始研究超级采样。如何去做这件事对我来说并不明显。这是我迄今为止尝试过的......
首先,我查看了Apple docs on anti-aliasing。我更新了我的像素格式初始化:
NSOpenGLPixelFormatAttribute attrs[] =
{
NSOpenGLPFADoubleBuffer,
NSOpenGLPFADepthSize, 24,
NSOpenGLPFAOpenGLProfile, NSOpenGLProfileVersion4_1Core,
NSOpenGLPFASupersample,
NSOpenGLPFASampleBuffers, 1,
NSOpenGLPFASamples, 4,
0
};
我还添加了glEnable(GL_MULTISAMPLE); 行。 GL_MULTISAMPLE_FILTER_HINT_NV 似乎没有定义(文档似乎已经过时了),所以我不确定在那里做什么。
这使我的渲染速度变慢,但似乎没有进行抗锯齿处理,因此我尝试了OpenGL Wiki on Multisampling 中描述的“Render-to-FBO”方法。我尝试了很多变体,结果多种多样:成功渲染(似乎没有抗锯齿),将垃圾渲染到屏幕上(有趣!),崩溃(应用程序消失,我得到一个系统对话框关于图形问题),并使我的笔记本电脑除了光标之外没有响应(在硬重启后得到关于图形问题的系统对话框)。
我在绘制之前检查了帧缓冲区的状态,所以我知道这不是问题所在。而且我确定我正在使用硬件而不是软件进行渲染 - 在其他帖子中看到了该建议。
我已经花了相当多的时间在这上面,但仍然不太明白如何处理这个问题。我想要一些帮助的一件事是如何查询 GL 以查看是否正确启用了超级采样,或者如何判断我的片段着色器被调用了多少次等等。我也对某些调用的位置有点困惑go - 我发现的大多数示例只是说明要调用哪些方法,但没有指定哪些方法需要在 draw 回调中执行。任何人都有一个简单的 SSAA 示例,带有 OpenGL 3 或 4 和 OSX...或其他可以尝试的东西?
编辑:绘图代码 - 超级坏(不要评判我),但供参考:
- (void)draw
{
glBindVertexArray(_vao); // todo: is this necessary? (also in init)
glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), points, GL_STATIC_DRAW);
glGenTextures( 1, &_tex );
glBindTexture( GL_TEXTURE_2D_MULTISAMPLE, _tex );
glTexImage2DMultisample( GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, _width * 2, _height * 2, false );
glGenFramebuffers( 1, &_fbo );
glBindFramebuffer( GL_FRAMEBUFFER, _fbo );
glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE, _tex, 0 );
GLint status;
status = glCheckFramebufferStatus( GL_FRAMEBUFFER );
if (status != GL_FRAMEBUFFER_COMPLETE) {
NSLog(@"incomplete buffer 0x%x", status);
return;
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo);
glDrawBuffer(GL_BACK);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBlitFramebuffer(0, 0, _width * 2, _height * 2, 0, 0, _width, _height, GL_COLOR_BUFFER_BIT, GL_LINEAR);
glDeleteTextures(1, &_tex);
glDeleteFramebuffers(1, &_fbo);
glBindFramebuffer( GL_FRAMEBUFFER, 0 );
}
更新: 我根据以下 Reto 的建议更改了代码:
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, _width * 2, _height * 2, 0, 0, _width, _height,
GL_COLOR_BUFFER_BIT, GL_LINEAR);
这导致程序将垃圾渲染到屏幕上。然后我去掉了* 2 乘数,它仍然在屏幕上画了垃圾。然后我关闭了与多重/超级采样相关的NSOpenGLPFA 选项,它正常渲染,没有抗锯齿。
我也尝试使用非多重采样纹理,但不断收到不完整的附件错误。我不确定这是否是由于 OpenGL wiki 上提到的 NVidia 问题(将发表评论,因为我没有足够的代表来发布超过 2 个链接)或其他原因。如果有人可以提出一种方法来找出附件不完整的原因,那将非常非常有帮助。
最后,我尝试使用渲染缓冲区而不是纹理,发现在 glRenderbufferStorage 中指定大于视口大小的宽度和高度似乎无法按预期工作。
GLuint rb;
glGenRenderbuffers(1, &rb);
glBindRenderbuffer(GL_RENDERBUFFER, rb);
glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, _width * 2, _height * 2);
// ...
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _fbo);
glClear(GL_COLOR_BUFFER_BIT);
glDrawArrays(GL_TRIANGLES, 0, 6);
glBindFramebuffer(GL_READ_FRAMEBUFFER, _fbo);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
glBlitFramebuffer(0, 0, _width * 2, _height * 2, 0, 0, _width, _height,
GL_COLOR_BUFFER_BIT, GL_LINEAR);
... 呈现在屏幕左下角的 1/4 处。不过好像不是更流畅...
更新 2: 将视口大小翻倍,并没有更流畅。转动NSOpenGLPFASupersample 仍然会导致它在屏幕上绘制垃圾。 >.
更新 3:我是个白痴,它完全更流畅。它只是看起来不太好,因为我使用的是丑陋的配色方案。而且我必须将所有坐标加倍,因为视口是 2x。那好吧。我仍然希望得到一些帮助来理解为什么 NSOpenGLPFASupersample 会导致如此疯狂的行为......
【问题讨论】:
-
NVidia + 不完整的纹理问题:opengl.org/wiki/Common_Mistakes#Render_To_Texture
-
您能分享一下您的 Mandelbrot 项目吗?我试图弄清楚如何在 OS X 上通过直接像素操作来制作 2d 图形,并且真的很难到达任何地方:(
-
@DanielLucraft 我会尝试将它放到 Github 上,但与此同时,我建议查看 Apple 的 GLEssentials example code。我发现它对入门非常有用。
-
好的,谢谢,会检查一下!
标签: macos cocoa opengl antialiasing