所以我有一个相当简单的实时2D游戏,我试图添加一些漂亮的光芒。把它归结为最基本的形式,它只是圆圈和黑色表面上绘制的谎言。如果你从hsv颜色空间的角度考虑场景,所有颜色(黑色除外)的“v”值都是100%。
目前我有一种“累积”缓冲区,其中当前帧与前一帧连接。它使用两个屏幕外缓冲区和黑色纹理。
目前所有“滞后”都来自cpu的延迟。 GPU可以很好地处理所有这些。
因此我想到的可能是通过为事物添加发光效果来尝试增加效果。我想的可能是第10步而不是使用常规纹理着色器,我可以使用一个绘制纹理除了发光!
不幸的是,我对如何做到这一点感到有点困惑。以下是一些原因
无论如何,我理解渲染辉光的过程是
到目前为止,我已经达到了一个可以绘制纹理的着色器。我的下一步是什么样的?
//Vertex
percision highp float;
attrivute vec2 positionCoords;
attribute vec2 textureCoords;
uniform mat4 matrix;
uniform float alpha;
varying vec2 v_texcoord;
varying float o_alpha;
void main()
{
gl_Position = matrix * vec4(positionCoords, 0.0, 1.0);
v_texcoord = textureCoords.xy;
o_alpha = alpha;
}
//Fragment
varying vec2 v_texcoord;
uniform sampler2D s_texture;
varying float o_alpha;
void main()
{
vec4 color = texture2D(s_texture, v_texcoord);
gl_FragColor = vec4(color.r, color.g, color.b, color.a - o_alpha);
}
这也是实时可行的事情吗?
编辑:我可能想要做5px或更少的模糊
答案 0 :(得分:0)
解决您最初的混淆项目:
glEnable(GL_BLEND)
的混合,并将模式设置为glBlendFunc()
。要进行快速一次通过全屏采样,您需要确定源纹理中的像素增量。静态确定此值最快,因此片段着色器无需在运行时计算它:
float dx = 1.0 / x_resolution_drawn_over;
float dy = 1.0 / y_resolution_drawn_over;
通过将纹理采样模式设置为GL_LINEAR
,并从源纹理t
中获取4个样本,您可以在一次传递中执行3像素(1,2,1)高斯模糊,如下所示:
float dx2 = 0.5*dx; float dy2 = 0.5*dy; // filter steps
[...]
vec2 a1 = vec2(x+dx2, y+dy2);
vec2 a2 = vec2(x+dx2, y-dy2);
vec2 b1 = vec2(x-dx2, y+dy2);
vec2 b2 = vec2(x-dx2, y-dy2);
result = 0.25*(texture(t,a1) + texture(t,a2) + texture(t,b1) + texture(t,b2));
通过将纹理采样模式设置为GL_LINEAR
,并从源纹理{{1}中获取9个样本,您可以在一次通过中执行5像素(1,4,6,4,1)高斯模糊如下:
t
我无法告诉您这些过滤器是否可以在您的平台上实时使用;全分辨率的9个样本/像素可能会很慢。
任何更宽的高斯将使单独的水平和垂直通道变得有利;实质上更宽的高斯需要多分辨率技术来实现实时性能。 (请注意,与高斯不同,过滤器如"焦点"模糊不可分离,这意味着它们不能分为水平和垂直通道......)
答案 1 :(得分:0)
@comingstorm所说的一切都是正确的,但有一种更简单的方法。不要写模糊或自己发光。既然你在iOS上,为什么不使用CoreImage,它有许多有趣的过滤器可供选择,哪些已经实时工作?例如,他们有一个Bloom过滤器,可能会产生您想要的结果。感兴趣的还有Gloom过滤器。
将CoreImage过滤器链接起来要比编写着色器容易得多。您可以通过[+CIImage imageWithTexture:size:flipped:colorSpace:]
从OpenGL纹理创建CIImage
。