通过将代码移到 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
显式着色器。
当编写着色器时,代码是针对每个(顶点/片段)执行的主函数之外的代码,还是每次绘制调用只执行一次,从而通过在绘制开始时预先计算许多值来提供好处。
例如,下面的顶点着色器会比下面的执行得更好吗?
#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
显式着色器。