Forums - Uniform value is wrong in adreno 305 qualcomm device but right in Adreno Profiler

8 posts / 0 new
Last post
Uniform value is wrong in adreno 305 qualcomm device but right in Adreno Profiler
cibermanu
Join Date: 26 Feb 15
Posts: 4
Posted: Tue, 2015-04-21 10:31

I´m doing my own game engine. Now, the next step is to build my fragment shader for multiple lighting sources. I found a very strange behaviour I can't understand. In my Moto G 2014 with an 305 Adreno video chip a glsl length function call gives me an incorrect value over a ambient lighting uniform, resulting in wrong scene lighting. Let's see for fist the fragment code:

#define numLights x
#pragma glsl

precision lowp float;

struct LightSourceParameters {
    vec3 ambient;
    vec3 lightColor;
    vec4 position;
    float spotExponent;
    float spotCutoff; // (range: [0.0,90.0], 180.0)
    vec3 spotDirection;
    float constantAttenuation;
    float linearAttenuation;
    float quadraticAttenuation;
};
uniform LightSourceParameters LightSource[numLights];

struct MaterialParameters {
    vec4 emission;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shininess;
    bool hasDiffuseTexture;
    bool hasSpecularTexture;
    bool hasEmissionTexture;
    bool hasAmbientTexture;
    bool hasNormalTexture;

    sampler2D emissionTexture;

    sampler2D diffuseTexture;
    sampler2D specularTexture;

    sampler2D ambientTexture;
    sampler2D normalTexture;
};
uniform MaterialParameters Material;

precision lowp float;

varying vec2 varyingTextcood;
varying vec3 varyingNormalDirection;
varying vec3 varyingViewDirection;
varying vec3 outLightVector[numLights];

void main()
{
    vec3 normalDirection = normalize(varyingNormalDirection);
    vec3 viewDirection = normalize(varyingViewDirection);
    vec3 lightDirection;
    float attenuation;
    // initialize total lighting with ambient lighting
    vec4 totalLighting;
    vec4 emissionTerm;
    if ((length(Material.emission) != 0.0) || (Material.hasEmissionTexture)) {
        /* El material tiene un termino emisivo, es decir, emite luz. Lo andimos al total de color calculado */
        if (!Material.hasEmissionTexture) {
            emissionTerm = Material.emission.rgba;
        }
        else {
            emissionTerm = texture2D(Material.emissionTexture, varyingTextcood).rgba;
        }
        if (emissionTerm.a > 0.0){
            totalLighting = emissionTerm;
        }
    }
    for (int index = 0; index < numLights; index++) // for all light sources
    {
        vec4 ambientalTerm;
        vec4 specularReflection;
        vec4 diffuseReflection;
        if (length(LightSource[index].ambient.rgb) > 0.0){
            // es luz ambiental
            if (Material.hasAmbientTexture){
                ambientalTerm = vec4(LightSource[index].ambient, 1.0) * texture2D(Material.ambientTexture, varyingTextcood);
            }
            else {
                ambientalTerm = vec4(LightSource[index].ambient, 1.0) * vec4(Material.ambient);
            }
            //totalLighting = vec4(0.0,1.0,0.0,1.0);
        }
        else {
            if (0.0 == LightSource[index].position.w) // directional light?
            {
                attenuation = 1.0; // no attenuation
                lightDirection = normalize(outLightVector[index]);
            }
            else // point light or spotlight (or other kind of light)
            {
                vec3 positionToLightSource = outLightVector[index];
                float distance = length(positionToLightSource);
                lightDirection = normalize(positionToLightSource);
                attenuation = 1.0 / (LightSource[index].constantAttenuation
                + LightSource[index].linearAttenuation * distance
                + LightSource[index].quadraticAttenuation * distance * distance);
                if (LightSource[index].spotCutoff <= 90.0) // spotlight?
                {
                    float clampedCosine = max(0.0, dot(-lightDirection, normalize(LightSource[index].spotDirection)));
                    if (clampedCosine < cos(radians(LightSource[index].spotCutoff))) // outside of spotlight cone?
                    {
                        attenuation = 0.0;
                    }
                    else
                    {
                        attenuation = attenuation * pow(clampedCosine, LightSource[index].spotExponent);
                    }
                }
            }
            vec4 diffuseTerm;
            if (Material.hasDiffuseTexture){
                diffuseTerm = texture2D(Material.diffuseTexture,varyingTextcood);
            }
            else {
                diffuseTerm = Material.diffuse;
            }
            if (diffuseTerm.a > 0.0){
                diffuseReflection = attenuation
                * vec4(LightSource[index].lightColor, 1.0) * diffuseTerm
                * max(0.0, dot(normalDirection, lightDirection));
            }
            if (dot(normalDirection, lightDirection) < 0.0) // light source on the wrong side?
            {
                specularReflection = vec4(0.0, 0.0, 0.0, 0.0); // no specular reflection
            }
            else // light source on the right side
            {
                vec4 specularTerm;
                if (Material.hasSpecularTexture){
                    specularTerm = texture2D(Material.specularTexture,varyingTextcood);
                }
                else {
                    specularTerm = Material.specular;
                }
                if (specularTerm.a > 0.0){
                    /* OPCION SIN HALFVECTOR
                    specularReflection = attenuation * vec4(LightSource[index].lightColor,1.0) * specularTerm
                    * pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), Material.shininess);
                    */
                    // OPCION CON HALFVECTOR
                    vec3 light_half_vector = normalize(outLightVector[index] + viewDirection);
                    specularReflection = attenuation * vec4(LightSource[index].lightColor,1.0) * specularTerm
                    * pow(max(dot(light_half_vector, normalDirection), 0.0), Material.shininess);
                }
            }
        }
        totalLighting = totalLighting + ambientalTerm + diffuseReflection + specularReflection;
    }
    gl_FragColor = clamp(totalLighting, 0.0, 1.0);
}

Well, inside the main function, if we look at the foor loop, we have this line:

if (length(LightSource[index].ambient.rgb) > 0.0){
I found that debbuging with my Moto G, the shader always enter inside this statement, no matter that the scene hasn't an ambient light source. I can test this easyly writing totalLighting = vec4(1.0) inside the if branch.

This is not happening in the Adreno Profiler. I can't understand what's wrong because the profiler connects to the Moto G GPU and retrieves all the uniforms value, and ambient is a vec3 of 0.0 values. Even if I take a screen capture of the same device in the profiler I get the expected lighting behaviour in the profiler and a wrong behaviour in the phone. Shouldn't it be the same in both sites if they are connected?

As a curiosity, if I change the order of the declarations inside the LightSourceParameters I get very diferent results, and I can't understand why. For example, take a look at he screen capture I upload, all the scene gets red that is the color I'm using to clear the screen when the scene has been rendered with

GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);
It's red for debbuging prupourses.

This is the original image in the moto g phone, in the usual declaration of the uniforms I have:

Rendering in the moto g phone

The next one is the capture I get if I move the vec3 ambient declaration to the end of the LightSourceParameter struct:

Rendering in the phone moving the ambient light declaration to the end of the LightSourceParameters struct

And this is the profiler capture where you can see the value of the uniform. Doesn't matter if the ambient declaration is at the begining of the struct or the end, the result is the same, as I would expect in the phone:

Scene rendered through the Adreno profiler

Does somebody knows what is wrong here or what I'm missunderstanding ?

Edit 1:

Commenting out the if statement of the ambient light:

//if (0.0 < length(LightSource[index].ambient)){
I allow the flow to go ahead and calculate the diffuse and specular light/material data. This is not optimal, but it´s a way to debug so I´m going to use it for now. The scene keeps black except the yellow sun rays (like the first image) until I substitute the light color in the diffuse calculation with a vec3(1.0) in this way:

       /*
            diffuseReflection = attenuation
                        * vec4(LightSource[index].lightColor, 1.0) * diffuseTerm
                        * max(0.0, dot(normalDirection, lightDirection));
        */
            diffuseReflection = attenuation
                        * vec4(1.0,1.0,1.0, 1.0) * diffuseTerm
                        * max(0.0, dot(normalDirection, lightDirection));
This way the diffuse term is calculated as if It was being done in the Adreno profiler and the image is rendered well. So my supossition is that the full array of light struct has garbage in it or wrong data, but I cant understand why this is only happening in the moto g.

You can see all the screen captures in the thread in stack overflow I have opened for this: http://stackoverflow.com/questions/29731812/uniform-value-is-wrong-in-ad...

Unfortunally they there have not been able to help me

 
 
  • Up0
  • Down0
Ayo Moderator
Profile picture
Join Date: 23 Jan 15
Posts: 31
Posted: Fri, 2015-05-08 11:34

Thanks for the report, and apologies for the late response.

I created a small sample program using your supplied shader and was able to reproduce the problem on a Moto X and Snapdragon 801 device.

As a workaround, I moved the ambient out of the LightSourceParameters struct.

uniform LightSourceParameters LightSource[numLights];
uniform vec3 TestAmbient; // <- move 'ambient' out of above

Then I changed the "if" condition from "if (length(LightSource[index].ambient.rgb) > 0.0)" to "if (length(TestAmbient) > 0.0)"

I added "fragcolor = vec4( 1.0, 0.5, 0.5, 1.0);" after the "if", and after the "else" for that "if" above I added "fragcolor = vec4( 0.5, 0.5, 1.0, 1.0);". Then I multiplied the gl_FragColor by "fragcolor".

Here is the output when the program passes a "TestAmbient" uniform of length > 0 :

http://i.imgur.com/knMCsyo.jpg

And here is the output when the program passes a "TestAmbient" uniform of length <= 0:

http://i.imgur.com/lbWRjmF.jpg

I have submitted my sample with your struct problem to the graphics compiler team, and will let you know if/when there's any progress on that issue.

  • Up0
  • Down0
cibermanu
Join Date: 26 Feb 15
Posts: 4
Posted: Sun, 2015-05-10 16:43
Thanks for your answer.
 
Unfortunatelly your workaround looks not to be so usefull.
 
As I could try myself, all the LightSource data is corrupted.
 
I changed a little my shader, following your advices and trying to optimize. The result: now the ambient light is working, but not the difusse part of the light neither the specular and other info contained on the struct.
 
This is my new shader (in bold the important changes suggested by you). Take in mind that I can have more that a ambient light so I have an array of vec3 and not only one like you suggested, but this is working:
 
#define numLights x
#pragma glsl
precision lowp float;
struct MaterialParameters {
    vec4 emission;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shininess;
    bool hasDiffuseTexture;
    bool hasSpecularTexture;
    bool hasEmissionTexture;
    bool hasAmbientTexture;
    bool hasNormalTexture;
    sampler2D emissionTexture;
    sampler2D diffuseTexture;
    sampler2D specularTexture;
    sampler2D ambientTexture;
    sampler2D normalTexture;
}
;
uniform MaterialParameters Material;
struct LightSourceParameters {
    //vec3 ambient; comented for an error in adreno compiler: workaround --> unirform vec3 ambientLight[numLights];
    vec3 lightColor;
    vec4 position;
    float spotExponent;
    float spotCutoff;
    // (range: [0.0,90.0], 180.0)
    vec3 spotDirection;
    float constantAttenuation;
    float linearAttenuation;
    float quadraticAttenuation;
};
uniform LightSourceParameters LightSource[numLights];
uniform vec3 ambientLight[numLights]; // workaround for ambient error
 
varying vec2 varyingTextcood;
varying vec3 varyingNormalDirection;
varying vec3 varyingViewDirection;
varying vec3 outLightVector[numLights];
void main()
{
    vec3 normalDirection = normalize(varyingNormalDirection);
    vec3 viewDirection = normalize(varyingViewDirection);
    vec3 lightDirection;
    float attenuation;
    // initialize total lighting with ambient lighting
    vec4 totalLighting;
    vec4 emissionTerm;
    if ((length(Material.emission.rgb) != 0.0) || (Material.hasEmissionTexture)) {
        /* El material tiene un termino emisivo, es decir, emite luz. Lo andimos al total de color calculado */
        if (!Material.hasEmissionTexture) {
            emissionTerm = Material.emission.rgba;
        }
        else {
            emissionTerm = texture2D(Material.emissionTexture, varyingTextcood).rgba;
        }
        if (emissionTerm.a > 0.0){
            totalLighting = emissionTerm;
        }
    }
    // TERMINOS DE COLOR
    /* Primero declaramos los finales */
    vec4 ambientalReflection;
    vec4 specularReflection;
    vec4 diffuseReflection;
    /* Ahora calculamos el termino referente al material */
    vec4 diffuseTerm;
    if (Material.hasDiffuseTexture){
        diffuseTerm = texture2D(Material.diffuseTexture,varyingTextcood);
    }
    else {
        diffuseTerm = Material.diffuse;
    }
    vec4 specularTerm;
    if (Material.hasSpecularTexture){
        specularTerm = texture2D(Material.specularTexture,varyingTextcood);
    }
    else {
        specularTerm = Material.specular;
    }
    vec4 ambientalTerm;
    if (Material.hasAmbientTexture){
        ambientalTerm = texture2D(Material.ambientTexture, varyingTextcood);
    }
    else {
        ambientalTerm = Material.ambient;
    }
    // FIN DE TERMINOS DE COLOR
    for (int index = 0; index < numLights; index++) // for all light sources
    {
        // if (0.0 < length(LightSource[index].ambient)){ fails on adreno compiler: workarround
        if (length(ambientLight[index]) > 0.0){
            // es luz ambiental
            /* CALCULO DE TERMINO AMBIENTAL LUZ * MATERIAL */
            // ambientalReflection = vec4(LightSource[index].ambient, 1.0) * ambientalTerm; fails on adreno compiler: workarround
            ambientalReflection = vec4(ambientLight[index], 1.0) * ambientalTerm;
        }
        else {
            if (0.0 == LightSource[index].position.w) // directional light?
            {
                attenuation = 1.0;
                // no attenuation
                lightDirection = normalize(outLightVector[index]);
            }
            else // point light or spotlight (or other kind of light)
            {
                vec3 positionToLightSource = outLightVector[index];
                float distance = length(positionToLightSource);
                lightDirection = normalize(positionToLightSource);
                attenuation = 1.0 / (LightSource[index].constantAttenuation
                + LightSource[index].linearAttenuation * distance
                + LightSource[index].quadraticAttenuation * distance * distance);
                if (LightSource[index].spotCutoff <= 90.0) // spotlight?
                {
                    float clampedCosine = max(0.0, dot(-lightDirection, normalize(LightSource[index].spotDirection)));
                    if (clampedCosine < cos(radians(LightSource[index].spotCutoff))) // outside of spotlight cone?
                    {
                        attenuation = 0.0;
                    }
                    else
                    {
                        attenuation = attenuation * pow(clampedCosine, LightSource[index].spotExponent);
                    }
                }
            }
            /* CALCULO DE TERMINO DIFUSO LUZ * MATERIAL */
            if (diffuseTerm.a > 0.0){
                diffuseReflection = attenuation
                * vec4(LightSource[index].lightColor, 1.0) * diffuseTerm
                * max(0.0, dot(normalDirection, lightDirection));
            }
            if (dot(normalDirection, lightDirection) < 0.0) // light source on the wrong side?
            {
                specularReflection = vec4(0.0, 0.0, 0.0, 0.0);
                // no specular reflection
            }
            else // light source on the right side
            {
                /* CALCULO DE TERMINO ESPECULAR LUZ * MATERIAL */
                if (specularTerm.a > 0.0){
                    /* OPCION SIN HALFVECTOR
                    specularReflection = attenuation * vec4(LightSource[index].lightColor,1.0) * specularTerm
                    * pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), Material.shininess);
                    */
                    // OPCION CON HALFVECTOR
                    vec3 light_half_vector = normalize(outLightVector[index] + viewDirection);
                    specularReflection = attenuation * vec4(LightSource[index].lightColor,1.0) * specularTerm
                    * pow(max(dot(light_half_vector, normalDirection), 0.0), Material.shininess);
                }
            }
        }
        totalLighting = totalLighting + ambientalReflection + diffuseReflection + specularReflection;
    }
    gl_FragColor = clamp(totalLighting, 0.0, 1.0);
}
 
This is the final result:
 
 
As you can see, the info about textures or materials are absolutely right, but the lights are wrong
 
I have another version of this shader that is working fine in this matter, but is extremely slow and have very bad performance. All the structs are identical, but the functions are not. This is the code, in case you need. Why is this not failling having the same LightSource struct? I need a workaround because this is for my final degree job. Thanks.
 
Inefficient but working code:
 
#define numLights x
#pragma glsl
precision lowp float;
struct LightSourceParameters {
    vec3 ambient;
    vec3 lightColor;
    vec4 position;
    float spotExponent;
    float spotCutoff;
    // (range: [0.0,90.0], 180.0)
    vec3 spotDirection;
    float constantAttenuation;
    float linearAttenuation;
    float quadraticAttenuation;
}
;
uniform LightSourceParameters LightSource[numLights];
struct MaterialParameters {
    vec4 emission;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shininess;
    bool hasDiffuseTexture;
    bool hasSpecularTexture;
    bool hasEmissionTexture;
    bool hasAmbientTexture;
    bool hasNormalTexture;
    sampler2D emissionTexture;
    sampler2D diffuseTexture;
    sampler2D specularTexture;
    sampler2D ambientTexture;
    sampler2D normalTexture;
}
;
uniform MaterialParameters Material;
varying vec2 outTextCoord;
varying vec3 outNormal;
varying vec3 outViewVector;
varying vec3 outLightVector[numLights];
/* Declaramos cabecera de funcion, necesaria para que GLSL no diga que la funcion no existe, al definirse despues de main */
// vec4 computeLight(in MaterialParameters material, in LightSourceParameters lightSource, in vec3 normal, in vec2 textCoord, in vec3 lightVector, in vec3 halfVector);
vec4 computeLight(in LightSourceParameters lightSource, in vec3 normal, in vec3 lightVector, in vec3 halfVector);
vec4 computeEmissionLight();
void main(){
    // Normalize the incoming vectors
    lowp vec3 normal = normalize(outNormal);
    lowp vec3 viewVector = normalize(outViewVector);
    // BACKFACE CULLING:
    float NdotVV = dot(normal,viewVector);
    if (NdotVV <= 0.0){
        gl_FragColor = vec4(0.0,0.0,0.0,1.0);
    }
    else {
        // normalize lightvector, compute half vectors and lights
        vec4 totalColorLighting = vec4(0.0);
        for (int indexComputeLights = 0;
        indexComputeLights < numLights;
        indexComputeLights++){
            LightSourceParameters light = LightSource[indexComputeLights];
            vec3 currentLightVector = vec3(0.0);
            vec3 currentHalfVector = vec3(0.0);
            if (length(light.ambient) == 0.0 ){
                /* no es ambiental, que no tienen vector ni half vector */
                currentLightVector = outLightVector[indexComputeLights];
                // normalizamos posteriormente, para poder obtener la distancia a la luz del m�dulo de este vector
                currentHalfVector = normalize(outLightVector[indexComputeLights] + outViewVector);
            }
            /* Si la luz es ambiental, halfVector y lightVector son
            * indefinidos para esa luz, pero da igual porque no son
            * utilizados en el algoritmo que calcula las luces
            */
            vec4 current_computed_light_color = computeLight(light, normal, currentLightVector, currentHalfVector);
            if (current_computed_light_color.a > 0.0){
                totalColorLighting = totalColorLighting + current_computed_light_color;
            }
        }
        if ((length(vec3(Material.emission)) != 0.0) || (Material.hasEmissionTexture)) {
            totalColorLighting = totalColorLighting + computeEmissionLight();
        }
        totalColorLighting = clamp(totalColorLighting,vec4(0.0),vec4(1.0));
        /* Devolvemos el color de fragmento calculado para almacenarlo en el framebuffer */
        gl_FragColor = totalColorLighting;
    }
    /*
    if ((length(vec3(Material.emission)) != 0.0) || (Material.hasEmissionTexture)) {
        gl_FragColor = computeEmissionLight();
        //gl_FragColor.rgb *= gl_FragColor.a;
        //gl_FragColor.a = 0.0;
    }
    */
}
lowp vec4 computeEmissionLight(){
    vec4 totalEmissionColorLighting = vec4(0.0);
    if ((length(vec3(Material.emission)) != 0.0) || (Material.hasEmissionTexture)) {
        /* El material tiene un termino emisivo, es decir, emite luz. Lo andimos al total de color calculado */
        if (!Material.hasEmissionTexture) {
            totalEmissionColorLighting.rgba = Material.emission.rgba;
        }
        else {
            totalEmissionColorLighting.rgba = texture2D(Material.emissionTexture, outTextCoord).rgba;
            // totalEmissionColorLighting.rgb *= totalEmissionColorLighting.a;
            //if (totalEmissionColorLighting.a < 0.3) return vec4(1.0,0.0,0.0,1.0);
            // if (totalEmissionColorLighting.a < 0.3) discard;
            // if (length(totalEmissionColorLighting) < 1.5) return vec4(0.0);
            // totalEmissionColorLighting.a = 0.0;
            //return vec4(0.0,0.0,0.0,0.0);
        }
    }
    return totalEmissionColorLighting;
}
lowp vec4 computeLight(in LightSourceParameters lightSource,
in vec3 normal, in vec3 lightVector, in vec3 halfVector){
    vec3 normalizedLightVector = normalize(lightVector);
    float attenuation = 1.0;
    // no attenuation
    vec4 totalLightingColor = vec4(0.0,0.0,0.0,0.0);
    if (length(lightSource.ambient) > 0.0) {
        // es luz ambiente
        if (!Material.hasAmbientTexture){
            totalLightingColor = vec4(lightSource.ambient, 1.0) * Material.ambient;
        }
        else {
            totalLightingColor = vec4(lightSource.ambient, 1.0) * texture2D(Material.ambientTexture, outTextCoord);
        }
    }
    else {
        // Is not ambiental light
        // BACKLIGHT CULLING:
        float NdotLV = dot(normal, normalizedLightVector);
        if (NdotLV < 0.0 ) {
            // light source in the wrong side
            return vec4(0.0,0.0,0.0,0.0);
        }
        if (lightSource.position.w == 0.0) {
            // es un vector, por lo tanto es una luz direccional
            attenuation = 1.0;
            // no attenuation
        }
        else {
            // Is a point light or a spot light (LIGHTVECTOR EXPRESA UN VECTOR DESDE GL_FRAGCOORD HASTA LA LUZ, NO LA DIRECCION DE LA LUZ A SECAS): SACAMOS DISTANCIAS
            float distanceToLight = length(lightVector);
            attenuation = lightSource.constantAttenuation / ((1.0+lightSource.linearAttenuation*distanceToLight)*(1.0+lightSource.quadraticAttenuation*distanceToLight*distanceToLight));
            if (lightSource.spotCutoff <= 90.0){
                /* Is a spot light */
                vec3 spotDirection = normalize(lightSource.spotDirection);
                float clampedCosine = max(0.0, dot(-normalizedLightVector, spotDirection));
                if (clampedCosine < cos(radians(lightSource.spotCutoff))){
                    /* outside the spotlight cone */
                    attenuation = 0.0;
                    /* full attenuation */
                }
                else {
                    /* inside the spotlight cone */
                    attenuation = attenuation * pow(clampedCosine, lightSource.spotExponent);
                }
            }
        }
        if (!Material.hasDiffuseTexture) {
            /* El canal difuso no tiene textura */
            totalLightingColor = totalLightingColor + attenuation * vec4(lightSource.lightColor, 1.0) * Material.diffuse * max(0.0, NdotLV);
        }
        else {
            totalLightingColor = totalLightingColor + attenuation * vec4(lightSource.lightColor, 1.0) * texture2D(Material.diffuseTexture, outTextCoord) * max(0.0, NdotLV);
        }
        float NdotHV = max(dot(normal, halfVector), 0.0);
        /* Normal-dot-halfvector */
        if (!Material.hasSpecularTexture){
            totalLightingColor = totalLightingColor + attenuation * pow(NdotHV, (Material.shininess)) * vec4(lightSource.lightColor, 1.0) * Material.specular;
        }
        else {
            totalLightingColor = totalLightingColor + attenuation * pow(NdotHV, (Material.shininess)) * vec4(lightSource.lightColor, 1.0) * texture2D(Material.specularTexture, outTextCoord);
        }
    }
    return totalLightingColor;
}
 
 

 

  • Up0
  • Down0
Ayo Moderator
Profile picture
Join Date: 23 Jan 15
Posts: 31
Posted: Mon, 2015-05-11 11:21

Sorry if my reply was confusing: the compiler problem is caused by the struct.

So everything you need to use from within the struct has to be taken out of the struct, just like you did with 'ambient'. That is, you need to create arrays of everything inside the struct that is used in the code, so for example:

uniform vec3 lightColor[numLights];

uniform vec4 position[numLights];

...

uniform float spotCutoff[numLights];

An easier alternative to making all these changes to your shader is for you to use a device containing a Snapdragon 805. The problem only exists on Snapdragon 801 devices like your Moto G 2014, and your original sample works fine on my Snapdragon 805 device.

  • Up0
  • Down0
cibermanu
Join Date: 26 Feb 15
Posts: 4
Posted: Mon, 2015-05-11 17:05
Hello again, thank you very much for your help.
Although your solution worked the first time when I got the ambient light out of the structure, your advice to get all the lights parameters out of this is making it fail as before. And Adreno profiler is still working fine as expected, so I think is not my fault.
 
This is the resulting code that have applied your workaround. In bold major changes.
 
#define numLights x
#pragma glsl
precision lowp float;
struct MaterialParameters {
    vec4 emission;
    vec4 ambient;
    vec4 diffuse;
    vec4 specular;
    float shininess;
    bool hasDiffuseTexture;
    bool hasSpecularTexture;
    bool hasEmissionTexture;
    bool hasAmbientTexture;
    bool hasNormalTexture;
    sampler2D emissionTexture;
    sampler2D diffuseTexture;
    sampler2D specularTexture;
    sampler2D ambientTexture;
    sampler2D normalTexture;
};
uniform MaterialParameters Material;
//struct LightSourceParameters {
    //vec3 ambient; comented for an error in adreno compiler: workaround --> uniform vec3 ambientLight[numLights];
    // vec3 lightColor; comented for an error in adreno compiler: workaround --> uniform vec3 lightColor[numLights];
    // vec4 position; comented for an error in adreno compiler: workaround --> uniform vec4 positionLight[numLights];
    // float spotExponent; comented for an error in adreno compiler: workaround --> uniform float spotExponent[numLights];
    // float spotCutoff; // (range: [0.0,90.0], 180.0) comented for an error in adreno compiler: workaround --> uniform float spotCutoff[numLights];
    // vec3 spotDirection; comented for an error in adreno compiler: workaround --> uniform vec3 spotDirection[numLights];
    // float constantAttenuation; comented for an error in adreno compiler: workaround --> uniform float constantAttenuation[numLights];
    // float linearAttenuation; comented for an error in adreno compiler: workaround --> uniform float linearAttenuation[numLights];
    // float quadraticAttenuation; comented for an error in adreno compiler: workaround --> uniform float quadraticAttenuation[numLights];
//};
// uniform LightSourceParameters LightSource[numLights]; // comentado por error compilador adreno, separamos struct para workaround
uniform vec3 ambientLight[numLights]; // workaround for ambient error
uniform vec3 lightColor[numLights]; // workaround for lightcolor error
uniform vec4 positionLight[numLights]; // workaround for position error
uniform float spotExponent[numLights]; // workaround for spotExponent error
uniform float spotCutoff[numLights]; // workaround for spotCutoff error
uniform vec3 spotDirection[numLights]; // workaround for spotDirection error
uniform float constantAttenuation[numLights]; // workaround for constantAttenuation error
uniform float linearAttenuation[numLights]; // workaround for linearAttenuation error
uniform float quadraticAttenuation[numLights]; // workaround for quadraticAttenuation error
 
varying vec2 varyingTextcood;
varying vec3 varyingNormalDirection;
varying vec3 varyingViewDirection;
varying vec3 outLightVector[numLights];
void main()
{
    vec3 normalDirection = normalize(varyingNormalDirection);
    vec3 viewDirection = normalize(varyingViewDirection);
    vec3 lightDirection;
    float attenuation;
    // initialize total lighting with ambient lighting
    vec4 totalLighting;
    vec4 emissionTerm;
    if ((length(Material.emission.rgb) != 0.0) || (Material.hasEmissionTexture)) {
        /* El material tiene un termino emisivo, es decir, emite luz. Lo andimos al total de color calculado */
        if (!Material.hasEmissionTexture) {
            emissionTerm = Material.emission.rgba;
        }
        else {
            emissionTerm = texture2D(Material.emissionTexture, varyingTextcood).rgba;
        }
        if (emissionTerm.a > 0.0){
            totalLighting = emissionTerm;
            totalLighting.a = emissionTerm.a;
        }
    }
    // TERMINOS DE COLOR
    /* Primero declaramos los finales */
    vec4 ambientalReflection;
    vec4 specularReflection;
    vec4 diffuseReflection;
    /* Ahora calculamos el termino referente al material */
    vec4 diffuseTerm;
    if (Material.hasDiffuseTexture){
        diffuseTerm = texture2D(Material.diffuseTexture,varyingTextcood);
    }
    else {
        diffuseTerm = Material.diffuse;
    }
    vec4 specularTerm;
    if (Material.hasSpecularTexture){
        specularTerm = texture2D(Material.specularTexture,varyingTextcood);
    }
    else {
        specularTerm = Material.specular;
    }
    vec4 ambientalTerm;
    if (Material.hasAmbientTexture){
        ambientalTerm = texture2D(Material.ambientTexture, varyingTextcood);
    }
    else {
        ambientalTerm = Material.ambient;
    }
    // FIN DE TERMINOS DE COLOR
    for (int index = 0; index < numLights; index++) // for all light sources
    {
        // if (0.0 < length(LightSource[index].ambient)){ fails on adreno compiler: workaround
        if (length(ambientLight[index]) > 0.0){
            // es luz ambiental
            /* CALCULO DE TERMINO AMBIENTAL LUZ * MATERIAL */
            // ambientalReflection = vec4(LightSource[index].ambient, 1.0) * ambientalTerm; fails on adreno compiler: workaround
            ambientalReflection = vec4(ambientLight[index], 1.0) * ambientalTerm;
 
            ambientalReflection.a = ambientalTerm.a;
 
        }
        else {
            // if (0.0 == LightSource[index].position.w) // directional light? comentado por error del compilador adreno
            if (0.0 == positionLight[index].w) // directional light?
            {
                attenuation = 1.0;
                // no attenuation
                lightDirection = normalize(outLightVector[index]);
            }
            else // point light or spotlight (or other kind of light)
            {
                vec3 positionToLightSource = outLightVector[index];
                float distance = length(positionToLightSource);
                lightDirection = normalize(positionToLightSource);
                // attenuation = 1.0 / (LightSource[index].constantAttenuation comentado por error compilador adreno
                attenuation = 1.0 / (constantAttenuation[index]
                // + LightSource[index].linearAttenuation * distance comentado por error compilador adreno
                + linearAttenuation[index] * distance
                // + LightSource[index].quadraticAttenuation * distance * distance); comentado por error compilador adreno
                + quadraticAttenuation[index] * distance * distance);
                // if (LightSource[index].spotCutoff <= 90.0) // spotlight? comentado por error de compilador adreno
                if (spotCutoff[index] <= 90.0) // spotlight?
                {
                    // float clampedCosine = max(0.0, dot(-lightDirection, normalize(LightSource[index].spotDirection))); comentado por error de compilador adreno
                    float clampedCosine = max(0.0, dot(-lightDirection, normalize(spotDirection[index])));
                    // if (clampedCosine < cos(radians(LightSource[index].spotCutoff))) // outside of spotlight cone? comentado por error de compilador adreno
                    if (clampedCosine < cos(radians(spotCutoff[index]))) // outside of spotlight cone?
 
                    {
                        attenuation = 0.0;
                    }
                    else
                    {
                        // attenuation = attenuation * pow(clampedCosine, LightSource[index].spotExponent); comentado por error de compilador adreno
                        attenuation = attenuation * pow(clampedCosine, spotExponent[index]);
                    }
                }
            }
            /* CALCULO DE TERMINO DIFUSO LUZ * MATERIAL */
            if (diffuseTerm.a > 0.0){
                diffuseReflection = attenuation
                // * vec4(LightSource[index].lightColor, 1.0) * diffuseTerm comentado por error de compilador adreno
                * vec4(lightColor[index], 1.0) * diffuseTerm
                * max(0.0, dot(normalDirection, lightDirection));
                diffuseReflection.a = diffuseTerm.a;
            }
            if (dot(normalDirection, lightDirection) < 0.0) // light source on the wrong side?
            {
                specularReflection = vec4(0.0, 0.0, 0.0, 0.0);
                // no specular reflection
            }
            else // light source on the right side
            {
                /* CALCULO DE TERMINO ESPECULAR LUZ * MATERIAL */
                if (specularTerm.a > 0.0){
                    /* OPCION SIN HALFVECTOR
                    // specularReflection = attenuation * vec4(LightSource[index].lightColor,1.0) * specularTerm comentado por error de compilador adreno
                    specularReflection = attenuation * vec4(lightColor[index],1.0) * specularTerm
                    * pow(max(0.0, dot(reflect(-lightDirection, normalDirection), viewDirection)), Material.shininess);
                    */
                    // OPCION CON HALFVECTOR
                    vec3 light_half_vector = normalize(outLightVector[index] + viewDirection);
                    // specularReflection = attenuation * vec4(LightSource[index].lightColor,1.0) * specularTerm comentado por error de compilador adreno
                    specularReflection = attenuation * vec4(lightColor[index],1.0) * specularTerm
                    * pow(max(dot(light_half_vector, normalDirection), 0.0), Material.shininess);
 
                    specularReflection.a = specularTerm.a;
                }
            }
        }
        totalLighting = totalLighting + ambientalReflection + diffuseReflection + specularReflection;
    }
    gl_FragColor = clamp(totalLighting, 0.0, 1.0);
}
 
 
This is a snapshot of the result I get.
 
 
This is a screenshot of the result I get if I comment the code that checks if the light has ambiental terms (that is why not allowing the flow of the shader to continue and shows the whole scene in black)
 
 
So we are back to the same problem we had at first, but this time we are not using the structure of lights.
 
I am quite sure that the error, although it is related to the structure, it is not 100% because of this. As I told in the older comment, the inefficient code, with the same structure works well in the Moto G, but very slow.
 
If you can not give me a temporary solution or workaround I will wait for someone on your team, but please keep me informed as I need a solution for my final degree project.
 
Greetings, Manu.
  • Up0
  • Down0
carrado.grant@g...
Join Date: 20 Sep 12
Posts: 38
Posted: Wed, 2015-05-13 18:41

The issue is not whose at fault. Without going into detail this IS a driver bug and mod is suggesting a potential workaround for the issue. No mention was made that this was your fault as that how I think you are interpreting the feedback. The emulator will most likey give different result ( I have seen this from personal experience ) as that just a translator that hands off the OpenGL/GLSL calls to the host device driver, in other words its using OpenGL and NOT OpenGLES natively.

  • Up0
  • Down0
Ayo Moderator
Profile picture
Join Date: 23 Jan 15
Posts: 31
Posted: Thu, 2015-05-14 15:33

Sorry to hear that the experiment with the struct didn't work. However, note that "MaterialParameters" is still using a struct.

Just to be sure we have checked everything, what is 'x' in this #define?

#define numLights x

Note that when I originally tried out my sample test, I had to give a specific number ('1') instead of 'x' because the shader does not compile with 'x'. I saw these errors:

05-06 22:13:35.772: E/lengthTest(12817): Failed to compile the fragment shader with ERROR: Fragment shader compilation failed.
05-06 22:13:35.772: E/lengthTest(12817): ERROR: 0:33: 'x' : undeclared identifier
05-06 22:13:35.772: E/lengthTest(12817): ERROR: 0:33: '' : constant expression required
05-06 22:13:35.772: E/lengthTest(12817): ERROR: 0:33: '' : array size must be a constant expression
05-06 22:13:35.772: E/lengthTest(12817): ERROR: 0:68: '' : constant expression required
05-06 22:13:35.772: E/lengthTest(12817): ERROR: 0:68: '' : array size must be a constant expression
05-06 22:13:35.772: E/lengthTest(12817): ERROR: 0:91: '<' :  wrong operand types  no operation '<' exists that takes a left-hand operand of type 'int' and a right operand of type 'float' (or there is no acceptable conversion)
05-06 22:13:35.772: E/lengthTest(12817): ERROR: 6 compilation errors.  No code generated.
05-06 22:13:35.772: E/lengthTest(12817): Failed to initialize the shaders!

So I have to ask you if you could try changing 'x' to a specific number and let us know the results.

 

 


 

  • Up0
  • Down0
cibermanu
Join Date: 26 Feb 15
Posts: 4
Posted: Mon, 2015-06-08 13:24

Sorry for the late answer.

Yes, you change x in define for any number you want. Usually 1 or 2.

Thanks

  • Up0
  • Down0
or Register

Opinions expressed in the content posted here are the personal opinions of the original authors, and do not necessarily reflect those of Qualcomm Incorporated or its subsidiaries (“Qualcomm”). The content is provided for informational purposes only and is not meant to be an endorsement or representation by Qualcomm or any other party. This site may also provide links or references to non-Qualcomm sites and resources. Qualcomm makes no representations, warranties, or other commitments whatsoever about any non-Qualcomm sites or third-party resources that may be referenced, accessible from, or linked to this site.