现在的位置: 首页 > 综合 > 正文

WebGL自学教程——关于WebGL着色器中的自定义函数

2014年02月13日 ⁄ 综合 ⁄ 共 5518字 ⁄ 字号 评论关闭

首先看看下面的两个自定义函数:

vec2 GetV2TexCoord(void)

{
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_TEXCOORD) return a_v2TexCoord;
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_XY) return v_v4SrcPosition.xy;
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_XZ) return v_v4SrcPosition.xz;
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_YZ) return v_v4SrcPosition.yz;
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_XY) return v_v4Position.xy;
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_XZ) return v_v4Position.xz;
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_YZ) return v_v4Position.yz;
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_TEXCOORD) return a_v2TexCoord;
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_SRC_POSITION) return v_v4SrcPosition.xy;
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_POSITION) return v_v4Position.xy;
    return vec2(0.0, 0.0);//EJSWEBGLTEXTURECOORDTYPE.NONE或未知
}
vec3 GetV3TexCoord(void)
{
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_TEXCOORD) return vec3(a_v3TexCoord.xy, 1.0);
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_XY) return vec3(v_v4SrcPosition.xy, 1.0);
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_XZ) return vec3(v_v4SrcPosition.xz, 1.0);
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_YZ) return vec3(v_v4SrcPosition.yz, 1.0);
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_XY) return vec3(v_v4Position.xy, 1.0);
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_XZ) return vec3(v_v4Position.xz, 1.0);
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_YZ) return vec3(v_v4Position.yz, 1.0);
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE.CUBE_TEXCOORD) return a_v3TexCoord;
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE.CUBE_SRC_POSITION) return vec3(v_v4SrcPosition.xyz);
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE.CUBE_POSITION) return vec3(v_v4Position.xyz);
    return vec3(0.0, 0.0, 0.0);//EJSWEBGLTEXTURECOORDTYPE.NONE或未知

}

看起来好像没有问题,理论上也不应当有问题(EJSWEBGLTEXTURECOORDTYPE._2D_TEXCOORD之类的会被自动替换成*.0之类的数字,此处就不扯浮点数不能直接用==号比较的话)。实际上,编译也没有问题,但是,在链接到程序对象时,出现了下面的问题:

(144,4): error X4505: maximum temp register index exceeded
(149,4): error X4505: maximum temp register index exceeded
(154,4): error X4505: maximum temp register index exceeded
(154,4): error X4505: maximum temp register index exceeded
(149,4): error X4505: maximum temp register index exceeded

对WebGL的着色器代码,我不知道有什么离线编译和汇编工具,没能看到编译后的代码。不过,在我所使用FF上,估计最后是借助了DirectX的HLSL(首先在线编译着色器代码,然后将编译好的汇编代码交给HLSL链接到程序)。链接过程中,对代码进行了重排和优化。可惜,做得不到位,有bug(在DirectX的HLSL,确实是有这么一个bug的,后来应当已经修正,但我没有更新过)。当然,这不是重点,重点是如果让上面的两个函数跑起来。

参考DirectX的HLSL的bug,发现问题发生在返回值使用的临时变量上:第一个返回的临时变量使用寄存器123,第二个返回的临时变量使用寄存器456,而不是使用寄存器123(只是为了说明问题,事实并不绝对如此)。最终,导致整个函数中需要使用的寄存器数量太多。既然如此,那就不使用返回临时变量。修改为:

void GetV2TexCoord(out vec2 v2Value)
{
    if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_TEXCOORD) v2Value =  a_v2TexCoord;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_XY) v2Value = v_v4SrcPosition.xy;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_XZ) v2Value = v_v4SrcPosition.xz;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_YZ) v2Value = v_v4SrcPosition.yz;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_XY) v2Value = v_v4Position.xy;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_XZ) v2Value = v_v4Position.xz;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_YZ) v2Value = v_v4Position.yz;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_TEXCOORD) v2Value = a_v2TexCoord;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_SRC_POSITION) v2Value = v_v4SrcPosition.xy;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_POSITION) v2Value = v_v4Position.xy;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_POSITION) v2Value = v_v4Position.xy;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_POSITION) v2Value = v_v4Position.xy;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_POSITION) v2Value = v_v4Position.xy;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_POSITION) v2Value = v_v4Position.xy;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_POSITION) v2Value = v_v4Position.xy;
    else if(u_im4Modes[1][0] == EJSWEBGLTEXTURECOORDTYPE.CUBE_POSITION) v2Value = v_v4Position.xy;
    else v2Value = vec2(0.0, 0.0);//EJSWEBGLTEXTURECOORDTYPE.NONE或未知
}
void GetV3TexCoord(out vec3 v3Value)
{
    if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_TEXCOORD) v3Value = vec3(a_v3TexCoord.xy, 1.0);
    else if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_XY) v3Value = vec3(v_v4SrcPosition.xy, 1.0);
    else if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_XZ) v3Value = vec3(v_v4SrcPosition.xz, 1.0);
    else if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_SRC_POSITION_YZ) v3Value = vec3(v_v4SrcPosition.yz, 1.0);
    else if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_XY) v3Value = vec3(v_v4Position.xy, 1.0);
    else if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_XZ) v3Value = vec3(v_v4Position.xz, 1.0);
    else if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE._2D_POSITION_YZ) v3Value = vec3(v_v4Position.yz, 1.0);
    else if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE.CUBE_TEXCOORD) v3Value = a_v3TexCoord;
    else if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE.CUBE_SRC_POSITION) v3Value = vec3(v_v4SrcPosition.xyz);
    else if(u_im4Modes[1][1] == EJSWEBGLTEXTURECOORDTYPE.CUBE_POSITION) v3Value = vec3(v_v4Position.xyz);
    else v3Value = vec3(0.0, 0.0, 0.0);//EJSWEBGLTEXTURECOORDTYPE.NONE或未知
}

很愁人的写法,不过总算能解决问题了。

抱歉!评论已关闭.