0

I'm using GLSL shaders in my WebGL project, a recent Chrome update made my shaders not linking without error message. The problem occur when i use a uniform as a condition of a "if" in a fragment shader, like this example :

uniform int hasTexture;

void main(void) {
    if(hasTexture == 1) {
        // some code
    }
}

In the vertex shader, it works, and if i don't use an uniform here, it works too.

EDIT : Here is the full shader where my problem occur :

Vertex Shader :

attribute vec3 aVertexPosition;
attribute vec3 aVertexNormal;
attribute vec2 aVertexTextureCoord;

uniform mat4 uMVMatrix;
uniform mat4 uPMatrix;
uniform mat3 uNMatrix;
uniform mat4 uMVMatrixCenter;

uniform vec3 uSunPosition;
uniform int hasTexture;

uniform int hasNormal;

varying float vLightLength;
varying float vSpecularLength;
varying vec2 vTextureCoord;

uniform float shininess;

uniform float sunPower;

void main(void) {

    vec4 inposition = uMVMatrix * vec4(aVertexPosition, 1.0);

    gl_Position = uPMatrix * inposition;


    if(hasNormal == 1) {

        vec4 transformedLocation = (uMVMatrixCenter * vec4(uSunPosition, 1.0));
        vec3 sunPosition = transformedLocation.xyz;

        vec3 lightDirection = normalize(sunPosition - inposition.xyz);

        vec3 transformedNormal = uNMatrix * aVertexNormal;

        vec3 normal = normalize(transformedNormal);
        vLightLength = max(dot(normal, lightDirection), 0.0)*sunPower;



        vec3 eyeDirection = normalize(-inposition.xyz);
        vec3 reflectionDirection = reflect(-lightDirection, normal);


        vSpecularLength = pow(max(dot(reflectionDirection, eyeDirection), 0.0), 32.0)*sunPower;

    }
    else {
        vLightLength = 1.0;
        vSpecularLength = 0.0;
    }

    if(hasTexture == 1)
        vTextureCoord = aVertexTextureCoord;

}

And here is the fragment shader :

#ifdef GL_ES
precision highp float;
#endif

varying float vLightLength;
varying float vSpecularLength;
varying vec2 vTextureCoord;

uniform sampler2D uSampler;
uniform int hasTexture;


uniform float ambiantIntensity;
uniform vec3 diffuseColor;
uniform vec3 emissiveColor;
uniform vec3 specularColor;
uniform float shininess;
uniform float transparency;

void main(void) {

    if(hasTexture == 1) {
        gl_FragColor = vec4(texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)).rgb*(
            emissiveColor*(1.0-vLightLength)
            +diffuseColor*vLightLength
            +specularColor*vSpecularLength*shininess), 1.0-transparency); // *vLightLength
    }
    else {
        gl_FragColor = vec4((emissiveColor*(1.0-vLightLength)
                            +diffuseColor*vLightLength
                            +specularColor*vSpecularLength*shininess), 1.0-transparency);
    }
}

And here is the code compiling them :

for(i=0;i<shaderNames.length;i++) {
    vertexShader = gl.createShader(gl.VERTEX_SHADER);
    gl.shaderSource(vertexShader, shaderSourceList[i*2]);
    gl.compileShader(vertexShader);


    if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) {
        alert(gl.getShaderInfoLog(vertexShader));
        return;
    }

    fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
    gl.shaderSource(fragmentShader, shaderSourceList[i*2+1]);
    gl.compileShader(fragmentShader);

    if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) {
        alert(gl.getShaderInfoLog(fragmentShader));
        return;
    }

    shaderPrograms[i] = gl.createProgram();
    gl.attachShader(shaderPrograms[i], vertexShader);
    gl.attachShader(shaderPrograms[i], fragmentShader);
    gl.linkProgram(shaderPrograms[i]);

    if (!gl.getProgramParameter(shaderPrograms[i], gl.LINK_STATUS)) {
        alert("Could not initialise shader "+shaderNames[i]);
        return;
    }
}

The error returned here is "Could not initialise shader " followed by the name.

If i remove the "if(hasTexture == 1) {" from my code, it works.

EDIT 2 : I have installed WebGL inspector and i have now an error message for this buffer :

"Precisions for uniform hasTexture do not match between the vertex and fragment shader"

But i don't know what is wrong with my uniform.

  • 1
    Are you positive you are setting up your uniform locations properly after linking the shaders? This is a pretty trivial piece of code, either ANGLE (Chrome's OpenGL ES 2.0 layer) is completely worthless or you're not showing us the entire problem. I'd love to help you, but you have not given enough information to do anything useful with :-\ – Andon M. Coleman Sep 16 '13 at 04:26
  • What is the error message you are getting? – fintelia Sep 16 '13 at 19:19
  • I am stumped, I did everything I could think of, even counting uniform vectors (20 vertex, 8 fragment). Nothing about this shader violates any specifications, the only thing I can think of is you are running into register / instruction slot limits and ANGLE is not reporting this error properly. I would suggest combining `hasTexture` and `hasNormal` into a single integer uniform and using some sort of bitmask (e.g. if it has normals, add 0x02, if it has textures add 0x01) to get around this issue. This is a total hack, but it might be your only choice. – Andon M. Coleman Sep 18 '13 at 06:52

1 Answers1

0

Ok, apparently the problem is due to a same uniform used in both vertex and fragment shader, if i rename the "hasTexture" uniform to "hasTextureVS" in the vertex shader, it works !

I don't know why using the same uniform in both shaders is now forbidden since a recent Chrome update, but this workaround solve my problem.