GLSL | 'float'和'int'之间的算术运算中输入不匹配

时间:2014-10-21 13:06:52

标签: android-ndk glsl opengl-es-2.0

我尝试编译程序(我之前已经从Cg语言移植了它)。片段着色器是

precision mediump float;
precision mediump int;

uniform float time;
uniform float aspect;
uniform sampler2D sampler_main;

varying vec4 v_texCoord;

void main()
{
    vec3 ret;
    vec2 uv = v_texCoord.xy;

    float rad=sqrt((uv.x-0.5)*(uv.x-0.5)*4.0+(uv.y-0.5)*(uv.y-0.5)*4.0)*.7071067;
    float ang=atan(((uv.y-0.5)*2.0),((uv.x-0.5)*2.0));

    vec2 uv1 = (uv-0.5)*aspect.xy;

    float rad1 = .1/(length(uv1) + .1)) ;

    vec2 uv2 = vec2 (ang/3.14, rad1);
    uv2.y = uv2.y  +0.1*time;
    uv2.x = uv2.x  +.0*time;

    vec2 uv3 = vec2 (ang/3.14, rad1*1.5);
    uv3.y = uv3.y + 0.08*time ;
    uv3.x = uv3.x + time/32;

    vec3 crisp = 2*texture2D(sampler_main, uv2).xyz;
    vec3 lay1 = vec3 (0,0,1)*uv.y*pow(1-rad,8);
    crisp = 3*crisp * pow(rad,1);
    float mask = saturate(1-4*rad);
    ret = crisp + lay1*mask + mask * texture2D(sampler_main, uv).xyz;

    gl_FragColor.xyz = ret;
    gl_FragColor.w = 1.0;
}

我在网上遇到错误

uv3.x = uv3.x + time/32;

当我将其更改为

uv3.x = uv3.x + time/32.0;

问题已经解决,但我不了解问题的根源。

的问题
float mask = saturate(1-4*rad);                  => float mask = saturate(1.0-4.0*rad);
vec3 crisp = 2*texture2D(sampler_main, uv2).xyz; => vec3 crisp = 2.0*texture2D(sampler_main, uv2).xyz;
vec3 lay1 = vec3 (0,0,1)*uv.y*pow(1-rad,8);      => vec3 lay1 = vec3 (0,0,1)*uv.y*pow(1.0-rad,8.0); 
crisp = 3*crisp * pow(rad,1);                    => crisp = 3.0*crisp * pow(rad,1.0);

有人可以解释一下:

  1. 为什么我不能在同一个表达式中混合使用float和int常量?
  2. 是否有任何解决方法允许我将float和int混合使用?

2 个答案:

答案 0 :(得分:7)

早期GLSL不允许隐式演员表。所以尝试一个明确的演员:

uv3.x = uv3.x + time/float(32);

{4}在第4章(第16页)中说明:

  

OpenGL着色语言是类型安全的。

之间没有隐式转换

最近的GLSL允许隐式类型转换。 {4}}在第4章(第25页)中说明:

  

OpenGL着色语言是类型安全的。类型之间存在一些隐式转换。   具体如何以及何时发生这种情况将在4.1.10“隐式转换”一节中描述   本说明书中的其他部分引用。

稍后从第39页开始,有一个可能的隐式转换列表。

答案 1 :(得分:3)

由于您的问题有标记,因此相关规范是相应的OpenGL ES Shading Language规范。

在“5.8分配”(第46页)一节中说明:

  

lvalue-expression和rvalue-expression必须具有相同的类型。必须通过构造函数明确指定所有需要的类型转换。

和“5.9表达式”(第48页)一节:

  

算术二元运算符add(+),subtract( - ),multiply(*)和divide(/)对整数和浮点类型表达式(包括向量和矩阵)进行操作。两个操作数必须是相同的类型,或者一个可以是标量浮点数,另一个可以是浮点矢量或矩阵,或者一个可以是标量整数,另一个可以是整数向量。

您需要做的就是在float表达式中使用float常量。在第一个示例中,使用32.0代替32。如果您习惯于从C / C ++编写32.0f,那么细微的细节:与ES 2.0一起使用的GLSL版本支持f后缀。所以写32.0f是一个错误。它在ES 3.0中是允许的。

虽然我确信有些人会强烈不同意我的观点:我认为不支持这些自动类型转换是一个很好的功能。我相信始终了解您正在操作的类型并使用正确的类型,而不依赖于自动转换是有用的。类型安全很有价值,而C和C ++等语言的松散输入常常是错误的来源。