Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/opengl/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Bloom着色器性能_Java_Opengl_Glsl - Fatal编程技术网

Java 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 <

我从互联网上找到了一个简单漂亮的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 < 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
  • 结果应类似于:
    
    均匀的二维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+列;
    }
    }
    }
    
    您还可以考虑搜索更具体的GLSL优化提示(纹理获取)、优化器工具等

我在着色器中看到的一件事是,当
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,我错了吗?