2012-01-25 192 views
6

我正在使用OpenGL 2.0的2D iOS游戏,我想知道是否有可能写一个着色器,将轮廓图像与辉光。所有的图像都是2D精灵。我所看到的着色器示例是用于3D对象的,因此我不确定2D图像是否可能。OpenGL ES着色器轮廓2D图像

+0

所以你想添加的辉光就像是阴影? –

+0

图像周围会有柔和的边缘。 –

回答

7

您是否接受边缘检测滤镜(如Sobel),产生如the Wikipedia article所示的图像,然后对其结果进行高斯模糊处理,以柔化边缘并给予其更多辉光,然后合成该图像到你的场景?

实际上,您可能只需重复使用您所见过的3d轮廓着色器 - 尽管您可以在理论上检查深度数量(在ES中进行了一些扩展工作),但我见过的每一个对于渲染的图像。

编辑:在进一步的考虑中,拉普拉斯可能比索贝尔更容易应用,因为它可以作为一个简单的卷积着色器(如地址like this所述)完成。尽管为了在移动设备上安全起见,您可能最多需要坚持使用3x3内核,并为每种效果编写不同的着色器,而不是使用数据来完成。所以例如粗略的高斯模糊,写出长度:

void main() 
{ 
    mediump vec4 total = vec4(0.0); 
    mediump vec4 grabPixel; 

    total +=  texture2D(tex2D, texCoordVarying + vec2(-1.0/width, -1.0/height)); 
    total +=  texture2D(tex2D, texCoordVarying + vec2(1.0/width, -1.0/height)); 
    total +=  texture2D(tex2D, texCoordVarying + vec2(1.0/width, 1.0/height)); 
    total +=  texture2D(tex2D, texCoordVarying + vec2(-1.0/width, 1.0/height)); 

    grabPixel =  texture2D(tex2D, texCoordVarying + vec2(0.0, -1.0/height)); 
    total += grabPixel * 2.0; 

    grabPixel =  texture2D(tex2D, texCoordVarying + vec2(0.0, 1.0/height)); 
    total += grabPixel * 2.0; 

    grabPixel =  texture2D(tex2D, texCoordVarying + vec2(-1.0/width, 0.0)); 
    total += grabPixel * 2.0; 

    grabPixel =  texture2D(tex2D, texCoordVarying + vec2(1.0/width, 0.0)); 
    total += grabPixel * 2.0; 

    grabPixel = texture2D(tex2D, texCoordVarying); 
    total += grabPixel * 4.0; 

    total *= 1.0/16.0; 

    gl_FragColor = total; 
} 

而拉普拉斯边缘检测结果看起来相似,但具有不同的常量。

作为一种优化,您应该尽可能在顶点着色器而不是片段着色器中计算相对采样点,因为这样做会避免依赖纹理读取。

+0

也许我没有看正确的3D,但我看到的那些似乎在某种程度上对光源进行操作,而我没有给出它的2D。我对着色器很陌生,所以我可能忽略了这里的明显。 –

+0

许多后喷射式无线电单元着色器通过将边缘定义为前向边缘和后向边缘之间的连接来使用相机位置来检测边缘。你显然无法使用其中的一种。但是像索贝尔和拉普拉斯算子这样的方法在二维图像中寻找颜色不连续性以识别边缘,所以完全合适。在卷积滤波器上进行读取可能很明智,如果您还没有,那么可以研究拉普拉斯和高斯模糊。我为后者添加了一些匆忙组装的示例代码。 – Tommy