在Android,OpenGL上实现抗锯齿(FSAA?)

时间:2011-11-09 17:35:52

标签: android opengl-es antialiasing

我目前正在Android上使用OpenGL来绘制设置宽度线,除了Android上的OpenGL本身不支持这些线的抗锯齿这一事实外,它的效果很好。我做了一些研究,但是我仍然坚持如何实现自己的AA。

FSAA

我发现的第一个可能的解决方案是全屏抗锯齿。我已经阅读了关于这个主题的this page,但我很难理解如何实现它。

  • 首先,我不确定这里实施FSAA的整个概念。文章指出“一种简单的抖动方法是修改投影矩阵,在x和y中添加小的翻译”。这是否意味着我需要不断地快速移动同一条线,或者多次画同一条线?
  • 其次,文章说“要根据像素计算抖动偏移,将抖动量除以对象坐标场景的维度,然后乘以适当的视口尺寸”。对象坐标场景的维度与视口维度之间有什么区别? (我使用的是800 x 480分辨率)

现在,根据该文章中给出的信息,“抖动”坐标应该相对容易计算。根据我到目前为止的假设,这是我提出的(Java)......

float currentX = 50;
float currentY = 75;

// I'm assuming the "jitter" amount is essentially
// the amount of anti-aliasing (e.g 2x, 4x and so on)
int jitterAmount = 2;

// don't know what these two are
int coordSceneDimensionX;
int coordSceneDimensionY;

// I assume screen size
int viewportX = 800;
int viewportY = 480;

float newX = (jitterAmount/coordSceneDimensionX)/viewportX;
float newY = (jitterAmount/coordSceneDimensionY)/viewportY;

// and then I don't know what to do with these new coordinates

就FSAA而言,这就是我所拥有的

使用纹理消除抗锯齿

在我参考FSAA的同一文档中,还有一个页面简要讨论了如何使用纹理实现抗锯齿。但是,我不知道以这种方式实施AA的最佳方式是什么,以及它是否比FSAA更有效。

希望那里的人比我知道更多关于抗锯齿的知识,并且可以帮助我实现这一目标。非常感谢!

2 个答案:

答案 0 :(得分:2)

文章中提出的方法早于GPU时能够进行抗锯齿处理的时间。这种抖动渲染到累积缓冲区并不是真正的实时图形技术(它是一种广泛实现的用于离线渲染的抗锯齿形式)。

这些天你做的是请求抗锯齿的帧缓冲。而已。这里的关键字是多重采样。看到这个SO答案: How do you activate multisampling in OpenGL ES on the iPhone? - 虽然是为iOS编写的,但是为Android做这件事也遵循类似的路径。 AFAIK在Android上,此扩展名用于http://www.khronos.org/registry/gles/extensions/ANGLE/ANGLE_framebuffer_multisample.txt

答案 1 :(得分:2)

首先你引用的文章使用了累积缓冲区,它的存在我在OpenGL ES中确实存在疑问,但我可能在这里错了。如果ES中确实支持累积缓冲区,那么您至少必须在创建GL上下文时明确请求它(但这在Android中完成)。

请注意,此技术效率极低,也已弃用,因为现在GPU通常支持某种多重采样抗锯齿(MSAA)。您应该研究您的系统/ GPU /驱动程序是否支持多次采样。这可能要求您在上下文创建期间请求多重采样帧缓冲或类似的事情。

现在回到文章。本文的基本思想不是快速移动线,而是在非常微小的不同(在子像素精度)位置(在图像空间中)渲染线(或实际上整个场景)并平均这些多次渲染获得最终图像,每一帧。

所以你有一组样本位置(在[0,1]中),它们实际上是子像素位置。这意味着如果你有一个样本位置(0.25,0.75),你在渲染时将整个场景在x方向上移动大约四分之一像素,在y方向移动一个像素的四分之三(当然在屏幕空间中)。当您为每个不同的样本完成此操作时,将所有这些渲染平均在一起以获得最终的抗锯齿渲染。

对象坐标场景的维度基本上是对象空间中屏幕的维度(实际上是查看体积的近平面),或者更实际上是您传递到glOrtho或{{1}的值(或类似的功能,但glFrustum并不是那么明显)。要修改投影矩阵以实现此抖动,可以使用本文中提供的函数。

抖动量抗混叠因子,但是子像素采样位置。此上下文中的抗锯齿因子是样本数量,以及您执行的抖动渲染数量。如果我假设正确并且您尝试仅抖动线端点,那么您的代码将无法工作。您必须使用此抖动投影多次绘制整个场景,而不仅仅是这一行(它可以使用简单的黑色背景和适当的混合)。

您也可以在没有使用混合的累积缓冲区的情况下实现此目的(使用gluPerspectiveglBlendFunc(GL_CONSTANT_COLOR, GL_ONE),其中glBlendColor(1.0f/n, 1.0f/n, 1.0f/n, 1.0f/n)是抗锯齿因子/样本计数)。但请记住,像这样渲染整个场景而不仅仅是这一行。

但是就像说这种技术已经过时了,您应该寻找在ES平台上启用MSAA的方法。