我正在使用OpenGL ES 2.0(在Android上)绘制简单的2D场景,图像很少。我有背景图片和其他一些有alpha通道。
我想仅使用着色器程序在纹理中绘制非透明像素的轮廓。经过一番广泛的搜索后,我找不到示例代码。看起来GLES 2.0仍然不那么受欢迎。
您能提供一些示例代码或指出正确的方向,我可以找到有关如何执行此操作的更多信息吗?
答案 0 :(得分:2)
要使像素着色器绘制某些东西,需要有几何体。 据我所知,你想在这些图像周围画一个边框, 但生成的最外层片段是基本实现中的图像像素, 所以你要用任何边框透支它们。
如果你想要一个'直线边框',除了绘制图像三角形/四边形(GL_TRIANGLES,GL_QUADS)之外你不能做任何其他事情,并且在另一个调用中可以做大纲(使用GL_LINES),你可以在这里分享一个顶点。单四边形。 考虑一下,许多GPU无法有效地绘制线条)
否则,请参阅以下解决方案:
解决方案1:
纹理属性:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP_TO_BORDER)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP_TO_BORDER)
glTexParameterfv(GL_TEXTURE_2D,GL_TEXTURE_BORDER_COLOR,borderColor4f)
我从未对单个通道纹理使用颜色边框,因此需要验证此方法。
解决方案2:
与1类似,但要在片段着色器中进行计算以检查,纹理坐标是否在边框区域内,而不是纹理边框。没有修改,纹理坐标的标量范围从0.0到1.0。
纹理属性可能是:
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_S,GL_CLAMP)
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_WRAP_T,GL_CLAMP)
片段颜色可以通过以下任何方法确定:
矩形的另一个边框颜色属性,其中选择了纹素或边框颜色(可以是顶点属性,但更可能是均匀或常量)。
将alpha纹理与第二个纹理组合作为整个矩形的背景(如图片框),此处也选择了纹素。
其他一些数学函数
当然,颜色值可以混合用于图像/边框渐变。
编辑:
由于此类轮廓线段的数量,长度和位置会有所不同,甚至可能形成凹形,因此您需要使用几何着色器执行此操作,这在ES 2.0内核中不可用。您可以做的最好的事情是为CPU上的每个图像预先计算一个线路循环。在着色器中进行此类测试效率相当低甚至过度,具体取决于图像大小,实际运行它的硬件等。如果您使用顶点着色器绘制固定数量的线段并对其进行变换,则无法正确执行覆盖所有情况,至少不是没有巨大的努力和GPU工作量。
如果您打算更改相应纹理像素的颜色值,则片段着色器需要为每个相邻像素提取大量且不同数量的纹素,朝向纹理边缘,就像在所有其他实现中一样。这种强力技术通常是递归和迭代算法的替代,对于这些算法,CPU是更好的选择。因此,我建议您通过修改纹理或在片段着色器中生成第二个组合来实现。
基本上,你需要实现一个路径查找算法,它试图“绕过”任意边缘的不透明像素。
答案 1 :(得分:2)
根据a)Qaulity和b)你需要的速度,有几种方法可以做到这一点。常见的搜索字词是:
1)传统的方法是使用模板缓冲区并渲染到纹理
清除模板缓冲区(通常每帧执行一次)
glClear( GL_COLOR_BUFFER_BIT | DEPTH_BUFFER_BIT | STENCIL_BUFFER_BIT )
渲染到纹理
禁用深度写入
glDepthMask( 1 );
禁用颜色缓冲区写入
glColorMask( 0, 0, 0, 0 );
启用模板缓冲区设置模板以始终传递和替换
glStencilOp( GL_KEEP, GL_KEEP, GL_REPLACE );
glStencilFunc( GL_ALWAYS, 1, 1 );
将对象绘制到纹理
2)沿着额外的顶点传递,即哪个顶点以正确的缠绕顺序相邻,并动态生成额外的轮廓三角形。
请参阅:http://www.gamasutra.com/view/feature/1644/sponsored_feature_inking_the_.php?print=1
3)使用便宜的边缘检测。在顶点着色器中,检查法线与视图的点积。如果它介于:
之间-epsilon < 0 < epsilon
然后你有优势。
4)使用cheap-o-rama对象缩放。当然,它对凹面物体不起作用,但根据你的质量需求可能足够好&#34;
参考文献:
相关的SO问题:
答案 2 :(得分:0)
您的Alpha通道可以看作是灰度图像。寻找任何边缘检测/绘图算法。例如Canny边缘检测器(http://en.wikipedia.org/wiki/Canny_edge_detector)。或者也许更好的想法,如果你的图像不是程序性的,那就是预先计算边缘。
如果您的目标是混合各种图像,然后根据该混合的结果应用轮廓,请尝试渲染到纹理,然后在屏幕上再次渲染该纹理并执行边缘检测算法。