Performance iPad第1代上的低着色器性能

Performance iPad第1代上的低着色器性能,performance,ipad,opengl-es-2.0,shader,Performance,Ipad,Opengl Es 2.0,Shader,我有我的绘画应用程序,它是用OpenGLES1.0和一些石英编写的。 我正在尝试使用OpenGL ES 2.0重写它,以获得更好的性能和新功能。 我已经编写了两个着色器:一个渲染用户对纹理的输入,另一个根据一些规则将此纹理与其他纹理混合。 突然,我意识到第二个着色器在第一代iPad上工作的时间太长了——我只有10-15 fps。iPad2以每秒60多帧的速度完美运行。我有点震惊,因为最初的应用程序(OpenGL ES 1.0)在这两种设备上都可以正常工作。它只渲染两个多边形(但几乎全屏)。 我尝

我有我的绘画应用程序,它是用OpenGLES1.0和一些石英编写的。 我正在尝试使用OpenGL ES 2.0重写它,以获得更好的性能和新功能。 我已经编写了两个着色器:一个渲染用户对纹理的输入,另一个根据一些规则将此纹理与其他纹理混合。 突然,我意识到第二个着色器在第一代iPad上工作的时间太长了——我只有10-15 fps。iPad2以每秒60多帧的速度完美运行。我有点震惊,因为最初的应用程序(OpenGL ES 1.0)在这两种设备上都可以正常工作。它只渲染两个多边形(但几乎全屏)。 我尝试了一些优化,比如改变精度,注释了一些数学运算,硬编码了一些纹理调用——这有点帮助,但我离60 fps还很远。只有当我完全注释这个着色器的调用时,我才有60 fps

我错过什么了吗?我在OpenGL方面没有太多经验,但我相信这个着色器必须在两代设备上都能正常工作,就像原始应用程序一样。我的顶点和片段着色器是:

===================顶点着色器===================

uniform mat4 modelViewProjectionMatrix;

attribute vec3 position;
attribute vec2 texCoords;

varying vec2 fTexCoords;

void main()

{ 

    fTexCoords = texCoords;

    vec4 postmp = vec4(position.xyz, 1.0);
    gl_Position = modelViewProjectionMatrix * postmp;


}
        precision highp float;  

        varying lowp vec4 colorVarying;
        varying highp vec2 fTexCoords;
        uniform sampler2D texture; // black & white user should paint
        uniform sampler2D drawingTexture; // texture with user drawings I rendered earlier
        uniform sampler2D paperTexture; // texture of sheet of paper 
        uniform float currentArea; // which area we should not shadow
        uniform float isShadowingOn; // bool - should we shadow some areas of picture    

        void main()
        {
            // I pass 1024*1024 texture here but I only need 560*800 so I do some calculations to find real texture coordinates

            vec2 convertedTexCoords = vec2(fTexCoords.x * 560.0/1024.0, fTexCoords.y * 800.0/1024.0); 

            vec4 bgImageColor = texture2D(texture, convertedTexCoords);        
            float area = bgImageColor.a;        
            bgImageColor.a = 1.0;            
            vec4 paperColor = texture2D(paperTexture, convertedTexCoords);       
            vec4 drawingColor = texture2D(drawingTexture, convertedTexCoords);

    // if special area         
            if ( abs(area - 1.0) < 0.0001) {            
                // if shadowing ON        
                if (isShadowingOn == 1.0) {               
                   // if color of original image is black        
                    if ( (bgImageColor.r < 0.1) && (bgImageColor.g < 0.1) && (bgImageColor.b < 0.1) ) {        
                        gl_FragColor = vec4(bgImageColor.rgb, 1.0) * vec4(0.5, 0.5, 0.5, 1.0);         
                    }                    
                    // if color of original image is grey

                    else if ( abs(bgImageColor.r - bgImageColor.g) < 0.15 && abs(bgImageColor.r - bgImageColor.b) < 0.15 && abs(bgImageColor.g - bgImageColor.b) < 0.15 && bgImageColor.r < 0.8 && bgImageColor.g < 0.8 && bgImageColor.b < 0.8){   gl_FragColor = vec4(paperColor.rgb * bgImageColor.rgb * 0.4 - drawingColor.rgb * 0.4, 1.0);} 


                 else 
                 {    
                 gl_FragColor = vec4(bgImageColor.rgb, 1.0) * vec4(0.5, 0.5, 0.5, 1.0);     
                    }
                } 

                // if shadowing is OFF        
                else {           
                    // if color of original image is black    
                if ( (bgImageColor.r < 0.1) && (bgImageColor.g < 0.1) && (bgImageColor.b < 0.1) ) {
                    gl_FragColor = vec4(bgImageColor.rgb, 1.0); 
                } 

                    // if color of original image is gray
                else if ( abs(bgImageColor.r - bgImageColor.g) < 0.15 && abs(bgImageColor.r - bgImageColor.b) < 0.15 && abs(bgImageColor.g - bgImageColor.b) < 0.15 
                 && bgImageColor.r < 0.8 && bgImageColor.g < 0.8 && bgImageColor.b < 0.8){
                    gl_FragColor = vec4(paperColor.rgb * bgImageColor.rgb * 0.4 - drawingColor.rgb * 0.4, 1.0);

                    } 

                    // rest
                else {
                    gl_FragColor = vec4(bgImageColor.rgb, 1.0); 
                }


                }
            } 

    // if area of fragment is equal to current area
        else if ( abs(area-currentArea/255.0) < 0.0001 ) { 
            gl_FragColor = vec4(paperColor.rgb * bgImageColor.rgb - drawingColor.rgb, 1.0); 
        }

    // if area of fragment is NOT equal to current area 
        else {
            if (isShadowingOn == 1.0) {
                gl_FragColor = vec4(paperColor.rgb * bgImageColor.rgb - drawingColor.rgb, 1.0) * vec4(0.5, 0.5, 0.5, 1.0);        
            } else {
                gl_FragColor = vec4(paperColor.rgb * bgImageColor.rgb - drawingColor.rgb, 1.0);
            }
        }
    }
===================片段着色器===================

uniform mat4 modelViewProjectionMatrix;

attribute vec3 position;
attribute vec2 texCoords;

varying vec2 fTexCoords;

void main()

{ 

    fTexCoords = texCoords;

    vec4 postmp = vec4(position.xyz, 1.0);
    gl_Position = modelViewProjectionMatrix * postmp;


}
        precision highp float;  

        varying lowp vec4 colorVarying;
        varying highp vec2 fTexCoords;
        uniform sampler2D texture; // black & white user should paint
        uniform sampler2D drawingTexture; // texture with user drawings I rendered earlier
        uniform sampler2D paperTexture; // texture of sheet of paper 
        uniform float currentArea; // which area we should not shadow
        uniform float isShadowingOn; // bool - should we shadow some areas of picture    

        void main()
        {
            // I pass 1024*1024 texture here but I only need 560*800 so I do some calculations to find real texture coordinates

            vec2 convertedTexCoords = vec2(fTexCoords.x * 560.0/1024.0, fTexCoords.y * 800.0/1024.0); 

            vec4 bgImageColor = texture2D(texture, convertedTexCoords);        
            float area = bgImageColor.a;        
            bgImageColor.a = 1.0;            
            vec4 paperColor = texture2D(paperTexture, convertedTexCoords);       
            vec4 drawingColor = texture2D(drawingTexture, convertedTexCoords);

    // if special area         
            if ( abs(area - 1.0) < 0.0001) {            
                // if shadowing ON        
                if (isShadowingOn == 1.0) {               
                   // if color of original image is black        
                    if ( (bgImageColor.r < 0.1) && (bgImageColor.g < 0.1) && (bgImageColor.b < 0.1) ) {        
                        gl_FragColor = vec4(bgImageColor.rgb, 1.0) * vec4(0.5, 0.5, 0.5, 1.0);         
                    }                    
                    // if color of original image is grey

                    else if ( abs(bgImageColor.r - bgImageColor.g) < 0.15 && abs(bgImageColor.r - bgImageColor.b) < 0.15 && abs(bgImageColor.g - bgImageColor.b) < 0.15 && bgImageColor.r < 0.8 && bgImageColor.g < 0.8 && bgImageColor.b < 0.8){   gl_FragColor = vec4(paperColor.rgb * bgImageColor.rgb * 0.4 - drawingColor.rgb * 0.4, 1.0);} 


                 else 
                 {    
                 gl_FragColor = vec4(bgImageColor.rgb, 1.0) * vec4(0.5, 0.5, 0.5, 1.0);     
                    }
                } 

                // if shadowing is OFF        
                else {           
                    // if color of original image is black    
                if ( (bgImageColor.r < 0.1) && (bgImageColor.g < 0.1) && (bgImageColor.b < 0.1) ) {
                    gl_FragColor = vec4(bgImageColor.rgb, 1.0); 
                } 

                    // if color of original image is gray
                else if ( abs(bgImageColor.r - bgImageColor.g) < 0.15 && abs(bgImageColor.r - bgImageColor.b) < 0.15 && abs(bgImageColor.g - bgImageColor.b) < 0.15 
                 && bgImageColor.r < 0.8 && bgImageColor.g < 0.8 && bgImageColor.b < 0.8){
                    gl_FragColor = vec4(paperColor.rgb * bgImageColor.rgb * 0.4 - drawingColor.rgb * 0.4, 1.0);

                    } 

                    // rest
                else {
                    gl_FragColor = vec4(bgImageColor.rgb, 1.0); 
                }


                }
            } 

    // if area of fragment is equal to current area
        else if ( abs(area-currentArea/255.0) < 0.0001 ) { 
            gl_FragColor = vec4(paperColor.rgb * bgImageColor.rgb - drawingColor.rgb, 1.0); 
        }

    // if area of fragment is NOT equal to current area 
        else {
            if (isShadowingOn == 1.0) {
                gl_FragColor = vec4(paperColor.rgb * bgImageColor.rgb - drawingColor.rgb, 1.0) * vec4(0.5, 0.5, 0.5, 1.0);        
            } else {
                gl_FragColor = vec4(paperColor.rgb * bgImageColor.rgb - drawingColor.rgb, 1.0);
            }
        }
    }
高精度浮点;
变低vec4色变;
不同的高电平vec2 fTexCoords;
均匀二维纹理;//黑白用户应该画画
均匀采样2D drawingTexture;//我先前渲染的用户图形的纹理
均匀的纹理;//纸的纹理
均匀浮动电流面积;//我们不应该在哪一个区域设置阴影
均匀浮点数为shadowingon;//bool-我们应该给图片的某些区域加上阴影吗
void main()
{
//我在这里传递1024*1024纹理,但我只需要560*800,所以我做了一些计算来找到真实的纹理坐标
vec2 convertedTexCoords=vec2(fTexCoords.x*560.0/1024.0,fTexCoords.y*800.0/1024.0);
vec4 bgImageColor=texture2D(纹理,转换后的桌面);
浮动面积=bgImageColor.a;
bgImageColor.a=1.0;
vec4 paperColor=texture2D(paperTexture,converteddexcoords);
vec4 drawingColor=纹理2D(drawingTexture,转换后的装饰);
//如果是特殊区域
if(abs(面积-1.0)<0.0001){
//若隐若现
如果(isShadowingOn==1.0){
//如果原始图像的颜色为黑色
如果((bgImageColor.r<0.1)和&(bgImageColor.g<0.1)和&(bgImageColor.b<0.1)){
gl_FragColor=vec4(bgImageColor.rgb,1.0)*vec4(0.5,0.5,0.5,1.0);
}                    
//如果原始图像的颜色为灰色
否则如果(abs(bgImageColor.r-bgImageColor.g)<0.15&&abs(bgImageColor.r-bgImageColor.b)<0.15&&bgImageColor.r<0.8&&bgImageColor.g<0.8&&bgImageColor.b<0.8){gl u FragColor=vec4(paperColor.rgb*bgImageColor.rgb*0.4-drawingColor.rgb*0.4,1.0)}
其他的
{    
gl_FragColor=vec4(bgImageColor.rgb,1.0)*vec4(0.5,0.5,0.5,1.0);
}
} 
//如果阴影关闭
否则{
//如果原始图像的颜色为黑色
if((bgImageColor.r<0.1)和&(bgImageColor.g<0.1)和&(bgImageColor.b<0.1)){
gl_FragColor=vec4(bgImageColor.rgb,1.0);
} 
//如果原始图像的颜色为灰色
如果(abs(bgImageColor.r-bgImageColor.g)<0.15&&abs(bgImageColor.r-bgImageColor.b)<0.15&&abs(bgImageColor.g-bgImageColor.b)<0.15
&&bgImageColor.r<0.8&&bgImageColor.g<0.8&&bgImageColor.b<0.8){
gl_FragColor=vec4(paperColor.rgb*bgImageColor.rgb*0.4-drawingColor.rgb*0.4,1.0);
} 
//休息
否则{
gl_FragColor=vec4(bgImageColor.rgb,1.0);
}
}
} 
//如果碎片的面积等于当前面积
如果(abs(面积当前面积/255.0)<0.0001){
gl_FragColor=vec4(paperColor.rgb*bgImageColor.rgb-drawingColor.rgb,1.0);
}
//如果碎片的面积不等于当前面积
否则{
如果(isShadowingOn==1.0){
gl_FragColor=vec4(paperColor.rgb*bgImageColor.rgb-drawingColor.rgb,1.0)*vec4(0.5,0.5,0.5,1.0);
}否则{
gl_FragColor=vec4(paperColor.rgb*bgImageColor.rgb-drawingColor.rgb,1.0);
}
}
}

在着色器中执行分支非常昂贵,因为它消除了GPU并行运行着色器的可能性,并且在片段着色器中有很多分支(无论如何都应该尽可能快的一个着色器)。更糟糕的是,您正在基于GPU本身上计算的值进行分支,这也极大地消耗了您的性能


你真的应该尝试删除尽可能多的分支,而不是让GPU做一些“额外的工作”,例如。不尝试优化纹理图集和渲染所有东西(如果这是可能的话),这仍然会比你当前的版本快。如果这不起作用,请尝试将着色器拆分为多个较小的着色器,每个着色器只执行较大着色器的特定部分,并在CPU上而不是在GPU上进行分支(每次绘制调用只需执行一次,而不是对每个“像素”)。

超出JustSid关于着色器中分支的有效点,我发现这里还有其他一些问题。首先,如果我运行这个片段