着色器链接失败,仅在移动设备上没有错误消息

时间:2017-05-30 08:44:41

标签: javascript c++ shader opengl-es-2.0 emscripten

我正在研究用C ++编写的图形引擎。我们目前可以为桌面或网络构建(使用emscripten)。两个平台都使用OpenGL ES 2.0。

我有一个顶点和一个片段着色器:

顶点着色器

    #version 100
    attribute vec4 a_position;
    attribute vec2 a_texcoord;
    attribute vec3 a_normal;
    attribute vec3 a_tangent;
    attribute vec3 a_bitangent;

    uniform mat4 u_model;
    uniform mat4 u_view;
    uniform mat4 u_projection;
    uniform mat3 u_normalMatrix;

    varying vec2 v_texcoord;
    varying vec3 v_normal;
    varying vec3 v_fragPos;
    varying mat3 v_TBN;

    void main()
    {
        vec3 T = normalize(vec3(u_model * vec4(a_tangent, 0.0)));
        vec3 B = normalize(vec3(u_model * vec4(a_bitangent, 0.0)));
        vec3 N = normalize(vec3(u_model * vec4(a_normal, 0.0)));
        v_TBN = mat3(T, B, N);

        gl_Position = u_projection * u_view * u_model * a_position;
        v_texcoord = a_texcoord;
        v_normal = u_normalMatrix * a_normal;
        v_fragPos = vec3(u_model * a_position);
    };

片段着色器

    #version 100
    precision mediump float;

    varying vec2 v_texcoord;
    varying vec3 v_normal;
    varying vec3 v_fragPos;
    varying mat3 v_TBN;

    struct Material {
        sampler2D diffuse;
        sampler2D specular;
        sampler2D normal;
        float shininess;
    };

    struct Light {
        int type;
        vec3 position;
        vec3 direction;
        vec3 ambient;
        vec3 diffuse;
        vec3 specular;
        float constant;
        float linear;
        float quadratic;
        float cutOff;
        float outerCutOff;
    };

    const int MAX_LIGHTS = 16;

    uniform vec3 u_viewPos;
    uniform Material u_material;
    uniform Light u_lights[MAX_LIGHTS];
    uniform int u_lightCount;
    uniform bool normalMapping;

    vec3 calcDirLight(Light light, vec3 normal, vec3 viewDir);
    vec3 calcPointLight(Light light, vec3 normal, vec3 viewDir);
    vec3 calcSpotLight(Light light, vec3 normal, vec3 viewDir);

    void main()
    {
        vec3 lightOutput = vec3(0.0);
        vec3 norm = normalize(v_normal);
        if (normalMapping)
        {
            norm = texture2D(u_material.normal, v_texcoord).rgb;
            norm = normalize(norm * 2.0 - 1.0);
            norm = normalize(v_TBN * norm);
        }
        vec3 viewDir = normalize(u_viewPos - v_fragPos);

        for(int i = 0; i < MAX_LIGHTS; i++)
        {
            if (i >= u_lightCount){break;}
            if (u_lights[i].type == 0)
            {
                lightOutput += calcDirLight(u_lights[i], norm, viewDir)
            }
            else if (u_lights[i].type == 1)
            {
                lightOutput += calcPointLight(u_lights[i], norm, viewDir);
            }
            else if (u_lights[i].type == 2)
            {
                lightOutput += calcSpotLight(u_lights[i], norm, viewDir);
            }
        }

        gl_FragColor = vec4(lightOutput, 1.0);
    }

    vec3 calcDirLight(Light light, vec3 normal, vec3 viewDir)
    {
        vec3 lightDir = normalize(-light.direction);
        float diff = max(dot(normal, lightDir), 0.0);
        vec3 reflectDir = reflect(-lightDir, normal);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_material.shininess);
        vec3 ambient = light.ambient * vec3(texture2D(u_material.diffuse, v_texcoord));
        vec3 diffuse = light.diffuse * diff * vec3(texture2D(u_material.diffuse, v_texcoord));
        vec3 specular = light.specular * spec * vec3(texture2D(u_material.specular, v_texcoord));
        return (ambient + diffuse + specular);
    }

    vec3 calcPointLight(Light light, vec3 normal, vec3 viewDir)
    {
        vec3 lightDir = normalize(light.position - v_fragPos);
        float diff = max(dot(normal, lightDir), 0.0);
        vec3 reflectDir = reflect(-lightDir, normal);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_material.shininess);
        float distance = length(light.position - v_fragPos);
        float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
        vec3 ambient = light.ambient * vec3(texture2D(u_material.diffuse, v_texcoord));
        vec3 diffuse = light.diffuse * diff * vec3(texture2D(u_material.diffuse, v_texcoord));
        vec3 specular = light.specular * spec * vec3(texture2D(u_material.specular, v_texcoord));
        ambient *= attenuation;
        diffuse *= attenuation;
        specular *= attenuation;
        return (ambient + diffuse + specular);
    }

    vec3 calcSpotLight(Light light, vec3 normal, vec3 viewDir)
    {
        vec3 lightDir = normalize(light.position - v_fragPos);
        float diff = max(dot(normal, lightDir), 0.0);
        vec3 reflectDir = reflect(-lightDir, normal);
        float spec = pow(max(dot(viewDir, reflectDir), 0.0), u_material.shininess);
        float distance = length(light.position - v_fragPos);
        float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
        float theta = dot(lightDir, normalize(light.direction));
        float epsilon = light.cutOff - light.outerCutOff;
        float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0);
        vec3 ambient = light.ambient * vec3(texture2D(u_material.diffuse, v_texcoord));
        vec3 diffuse = light.diffuse * diff * vec3(texture2D(u_material.diffuse, v_texcoord));
        vec3 specular = light.specular * spec * vec3(texture2D(u_material.specular, v_texcoord));
        ambient *= attenuation * intensity;
        diffuse *= attenuation * intensity;
        specular *= attenuation * intensity;
        return (ambient + diffuse + specular);
    };

它们都编译没有错误,但链接阶段失败。信息日志(使用glGetProgramInfoLog访问)为空。

最大的问题是它在桌面本机和桌面浏览器(emscripten)上完全编译和链接。它只能在移动设备上无法链接。

我花了好几个小时试图解决这个问题,但没有成功。有什么明显的我可能错过了吗?

编辑1:这是构建着色器程序的代码:

    GLuint GLES2Shader::buildProgram(GLuint vertexShader, GLuint fragmentShader)
    {

        GL( GLuint programObject = glCreateProgram() );

        GL( glAttachShader(programObject, vertexShader) );
        GL( glAttachShader(programObject, fragmentShader) );

        GL( glLinkProgram(programObject) );

        //check if the program linked successfully
        GLint linked;
        GL( glGetProgramiv(programObject, GL_LINK_STATUS, &linked) );
        if (!linked)
        {
            DEBUG( GLchar infoLog[512] );
            DEBUG( glGetProgramInfoLog(programObject, 512, NULL, infoLog) );
            DEBUG( LOGE("ERROR::SHADER::LINKING_FAILED %s", infoLog) );

            GL( glDeleteProgram(programObject) );
            return 0;
        }
        return programObject;
    }

0 个答案:

没有答案