adreno 305 qualcom设备中的统一值是错误的,但在Adreno Profiler中是正确的

时间:2015-04-19 15:24:45

标签: android graphics glsl opengl-es-2.0 gpu

我在做我自己的游戏引擎。现在,下一步是为多个光源构建片段着色器。 我发现了一种我无法理解的非常奇怪的行为。在我的Moto G 2014中使用305 Adreno视频芯片时,glsl长度函数调用在环境照明均匀度上给出了不正确的值,导致错误的场景照明。 让我们先看一下片段代码:

#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);
}

好吧,在main函数中,如果我们看一下foor循环,我们就有了这一行:

if (length(LightSource[index].ambient.rgb) > 0.0){

我发现使用我的Moto G进行重新布线时,无论场景中没有环境光源,着色器始终都会进入此声明。我可以在if分支中轻松编写totalLighting = vec4(1.0)。

Adreno Profiler中没有发生这种情况。我无法理解什么是错的,因为探查器连接到Moto G GPU并检索所有制服值,而环境是0.0值的vec3。即使我在探查器中截取同一设备的屏幕截图,我也会在探查器中获得预期的照明行为,并在手机中显示错误的行为。如果它们连接在一起,它们不应该是相同的吗?

作为一个好奇心,如果我改变LightSourceParameters中声明的顺序,我会得到非常不同的结果,我无法理解为什么。例如,看一下我上传的屏幕截图,所有场景都变成红色,这是我在用场景渲染时用来清除屏幕的颜色

GLES20.glClear(GLES20.GL_DEPTH_BUFFER_BIT | GLES20.GL_COLOR_BUFFER_BIT);

对于补偿prupourses来说,这是红色的。

这是moto g手机中的原始图片,通常我的制服宣言:

Rendering in the moto g phone

下一个是我将vec3环境声明移动到LightSourceParameter结构的末尾时获取的捕获:

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

这是探查器捕获,您可以在其中看到制服的价值。无论环境声明是在结构的开头还是结尾,结果都是一样的,就像我在电话中所期望的那样:

Scene rendered through the Adreno profiler

有人知道这里有什么问题或我误解了什么吗?

编辑1:

注释环境光的if语句:

//if (0.0 < length(LightSource[index].ambient)){

我允许流程继续并计算漫反射和镜面反射光/材料数据。这不是最佳选择,但它是一种调试方式,所以我现在要使用它。除了黄色太阳光线(如第一个图像)之外,场景保持黑色,直到我用这样的方式用漫画计算(1.0)替换漫反射计算中的光色:

       /*
            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));

这样计算漫反射项,好像它是在Adreno分析器中完成的,并且图像渲染得很好。所以我的说法是,完整的light struct数组中有垃圾或数据错误,但我不明白为什么这只发生在moto g中。

0 个答案:

没有答案