Java Bloom着色器性能
我从互联网上找到了一个简单漂亮的bloom着色器,但速度相对较慢 从外观上看,这里的罪魁祸首是嵌套循环和其中的纹理查找 我怎样才能让它跑得更快Java Bloom着色器性能,java,opengl,glsl,Java,Opengl,Glsl,我从互联网上找到了一个简单漂亮的bloom着色器,但速度相对较慢 从外观上看,这里的罪魁祸首是嵌套循环和其中的纹理查找 我怎样才能让它跑得更快 uniform sampler2D u_texture; varying vec2 v_texCoords; void main() { vec4 sum = vec4(0); vec2 texcoord = vec2(v_texCoords); int j; int i; for (i = -2; i <
uniform sampler2D u_texture;
varying vec2 v_texCoords;
void main() {
vec4 sum = vec4(0);
vec2 texcoord = vec2(v_texCoords);
int j;
int i;
for (i = -2; i < 2; i++) {
for (j = -2; j < 2; j++) {
sum += texture2D(u_texture, texcoord + vec2(j, i)*0.004) * 0.25;
}
}
if (texture2D(u_texture, texcoord).r < 0.3) {
gl_FragColor = sum*sum*0.012 + texture2D(u_texture, texcoord);
} else {
if (texture2D(u_texture, texcoord).r < 0.5) {
gl_FragColor = sum*sum*0.009 + texture2D(u_texture, texcoord);
} else {
gl_FragColor = sum*sum*0.0075 + texture2D(u_texture, texcoord);
}
}
}
均匀采样2D u_纹理;
可变矢量2 v_texCoords;
void main(){
vec4和=vec4(0);
vec2 texcoord=vec2(v_texCoords);
int j;
int i;
对于(i=-2;i<2;i++){
对于(j=-2;j<2;j++){
sum+=texture2D(u_纹理,texcoord+vec2(j,i)*0.004)*0.25;
}
}
if(纹理2D(u_纹理,texcoord).r<0.3){
gl_FragColor=sum*sum*0.012+纹理2d(u_纹理,texcoord);
}否则{
if(纹理2d(u_纹理,texcoord).r<0.5){
gl_FragColor=sum*sum*0.009+纹理2d(u_纹理,texcoord);
}否则{
gl_FragColor=sum*sum*0.0075+纹理2d(u_纹理,texcoord);
}
}
}
我不确定“手动优化”GLSL是否合理,但您可以尝试:
- 手动展开循环(对于(i=-2;i<2;i++),对于(j=-2;j<2;j++),它将为您提供16行而不是5行,但“优化”代码通常看起来“不优雅”,通常此操作应由编译器完成
- 将纹理2D(u_纹理,texcoord)存储在向量中
- 不要重复计算sum*sum
- 结果应类似于:
您还可以考虑搜索更具体的GLSL优化提示(纹理获取)、优化器工具等均匀的二维u_纹理; 可变矢量2 v_texCoords; void main(){ vec4和=vec4(0); vec4列=vec4(0); vec2 texcoord=vec2(v_texCoords); 总和+=纹理2D(u_纹理,texcoord+vec2(-2,-2)*0.004)*0.25; 总和+=纹理2D(u_纹理,texcoord+vec2(-2,-1)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(-2,0)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(-2,1)*0.004)*0.25; 总和+=纹理2D(u_纹理,texcoord+vec2(-1,-2)*0.004)*0.25; 总和+=纹理2D(u_纹理,texcoord+vec2(-1,-1)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(-1,0)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(-1,1)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(0,-2)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(0,-1)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(0,0)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(0,1)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(1,-2)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(1,-1)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(1,0)*0.004)*0.25; sum+=texture2D(u_纹理,texcoord+vec2(1,1)*0.004)*0.25; 总和*=总和; col=纹理2D(u_纹理,texcoord); 如果(列r<0.3){ gl_FragColor=0.012+色; }否则{ 如果(列r<0.5){ gl_FragColor=总和*0.009+列; }否则{ gl_FragColor=总和*0.0075+列; } } }
。
col.r<0.3
时,它不需要运行。这意味着在运行bloom着色器时,可以使用模具排除这些部分(因此着色器不会在这些像素上运行)这是bloom的问题,它的速度很慢,因为它在嵌套循环中查询纹理25次。这是一个可分离的过滤器,有时两次(水平和垂直)比1快-特别是当您开始使用较大的示例窗口(这是5x5内核)时。您还可以利用硬件的内置功能,一次快速采样和平均4个texel(线性过滤)。呃,现在我仔细看一下,这是一个4x4内核。你为什么这么做?我认为你的循环应该包括I,j=2,而不是结束在那里。理想情况下,它将被分为两个过程,因此每个过程只需I[-2,2]=5次抓取。您也可以在求和结束时进行乘法,手动展开循环似乎有问题。您不知道在所有体系结构上展开的版本是否会更快。编译器应该能够对展开是否有益做出更明智的决定。正如@ratchetfreak指出的,您可以消除一些操作。中心点的纹理查找仍会执行两次。但我怀疑这都是些小改进。25个纹理查找很可能会主导其他所有内容。为什么是25个?我,j:{-2,-1,0,1}那么“只是”16,我错了吗?