通过将代码移到 main(){} 之外来优化着色器

Shader optimisation by moving code outside main(){}

当编写着色器时,代码是针对每个(顶点/片段)执行的主函数之外的代码,还是每次绘制调用只执行一次,从而通过在绘制开始时预先计算许多值来提供好处。

例如,下面的顶点着色器会比下面的执行得更好吗?

#attribute vec4 position;
#attribute vec2 texcoord;
// desc. Sprite description array items in order
// startCoord, endCoord, ununsed  , textScale,(unused,screenAspect),(alpha,scale),unused,tile
#uniform vec2 desc[8];   
varying vec2 v_texcoord;
varying float alpha;
const vec2 proj = vec2(-0.5, 0.5);

//---------------------------------------------------------------------
// Does the following code only run once per draw code.
// code common to all verts
float aspect = desc[4].y;
vec2 aspectV = vec2(1.0,aspect);
vec2 line   =  desc[1] - desc[0]; 
vec2 lineI  =  normalize(line / aspectV);
float len   =  length(line / aspectV) *2.0;
vec2 lineJ  =  lineI * desc[3].y * desc[5].y;
vec2 textX  =  vec2(len / desc[5].y / desc[3].x / 2.0, 1.0);
mat4 tMat   =  mat4(1);  // if I change this to include assigning the 
                         // vectors lineI and lineJ will this provide a 
                         // performance benefit.
//---------------------------------------------------------------------

void main() {
   tMat[0][0] = lineI.x ;
   tMat[0][1] = lineI.y * aspect;
   tMat[1][0] = lineJ.y;
   tMat[1][1] = -lineJ.x * aspect;
   gl_Position  = (tMat * vec4(position.xy * vec2(len,2.0), position.zw)) +  vec4((desc[0] + proj) * 2.0, 0.0, 0.0);
   v_texcoord = texcoord * textX;
   alpha = desc[5].x;
} 

所有代码都在 main 里面,这么慢吗?

#attribute vec4 position;
#attribute vec2 texcoord;
// desc. Sprite description array items in order
// startCoord, endCoord, ununsed  , textScale,(unused,screenAspect),(alpha,scale),unused,tile
#uniform vec2 desc[8];   
varying vec2 v_texcoord;
varying float alpha;
const vec2 proj = vec2(-0.5, 0.5);

void main() {
   float aspect = desc[4].y;
   vec2 aspectV =   vec2(1.0,aspect);
   vec2 line  = desc[1] - desc[0]; 
   vec2 lineI = normalize(line / aspectV);
   float len  = length(line / aspectV) *2.0;
   vec2 lineJ = lineI * desc[3].y * desc[5].y;
   vec2 textX = vec2(len / desc[5].y / desc[3].x / 2.0, 1.0);
   mat4 tMat  = mat4(1);  
   tMat[0][0] = lineI.x ;
   tMat[0][1] = lineI.y * aspect;
   tMat[1][0] = lineJ.y;
   tMat[1][1] = -lineJ.x * aspect;
   gl_Position  = (tMat * vec4(position.xy * vec2(len,2.0), position.zw)) +  vec4((desc[0] + proj) * 2.0, 0.0, 0.0) ;
   v_texcoord = texcoord * textX;
   alpha = desc[5].x;
}` 

我将忽略 #attribute#uniform 不是合法的 GLSL 构造这一事实。我假设您使用的是真正合法的 GLSL。

您的问题本质上是您是否希望调用 glUniform 来实际更新所有这些全局变量的值。

我不希望实现中有这样的优化。这些类型的优化很难做到,因为它们涉及隐式统一值的创建。这可以增加着色器使用的 有效 制服的数量,可能超过合法的制服数量。

如果您想确保这些预计算是在每次绘制调用时完成的,那么应该进行这些计算并使结果成为您提供给 uniform显式着色器。