微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

OpenGL ES 2.0 GLSL 着色器无法编译

如何解决OpenGL ES 2.0 GLSL 着色器无法编译

我有一个带有简单着色器的 OpenGL 应用,该应用在 Android Studio 中的模拟器设备上运行良好,带有 API 30,但在我自己的硬件设备 (API 30) 上却没有。

问题出在片段着色器中。这是代码

#version 100

precision highp float;


struct DirLight {
    int on;
    vec3 direction;
    vec3 ambientColor;
    vec3 diffuseColor;
    vec3 specularColor;
    float specularExponent;
    sampler2D shadowMap;
    mat4 shadowVPMatrix;
    int shadowEnabled;
};

struct PointLight {
    int on;
    vec3 position;
    float constant;
    float linear;
    float quadratic;
    vec3 ambientColor;
    vec3 diffuseColor;
    vec3 specularColor;
    float specularExponent;
    sampler2D shadowMap;
    mat4 shadowVPMatrix;
    int shadowEnabled;
};

#define MAX_NUM_POINT_LIGHTS 8

uniform DirLight uDirLight;
uniform PointLight uPointLights[MAX_NUM_POINT_LIGHTS];
uniform int uNumPointLights;
uniform vec3 uViewPos;
uniform sampler2D uTexture;
uniform int uIsTextured;
varying vec4 vColor;
varying vec4 vPosition;
varying vec3 vnormal;
varying vec2 vTexCoords;
const vec4 bitShifts = vec4(1.0 / (256.0*256.0*256.0),1.0 / (256.0*256.0),1.0 / 256.0,1.0);



vec4 getColor(){
    if (uIsTextured != 0){
        return texture2D(uTexture,vTexCoords);
    }
    return vColor;
}

float unpack(vec4 color){
    return dot(color,bitShifts);
}

// return 0.0 if in shadow.
// return 1.0 if not in shadow.
float calcShadow(sampler2D shadowMap,vec4 positionFromLight,int shadowEnabled){
    if (shadowEnabled == 0){
        return 1.0;
    }
    vec3 positionFromLight3 = positionFromLight.xyz / positionFromLight.w;
    positionFromLight3 = (positionFromLight3 + 1.0) / 2.0;
    float closestFragmentZ = unpack(texture2D(shadowMap,positionFromLight3.xy));
    float currentFragmentZ = positionFromLight3.z;
    return float(closestFragmentZ > currentFragmentZ);
}

float diffuseLighting(vec3 normal,vec3 lightDir){
    return max(dot(normal,lightDir),0.0);
}

float specularLighting(vec3 normal,vec3 lightDir,vec3 viewDir,float specularExponent){
    vec3 reflectDir = reflect(-lightDir,normal);
    return pow(max(dot(viewDir,reflectDir),0.0),specularExponent);
}

vec4 calcDirLight(vec3 normal,vec3 viewDir){
    vec3 lightDir = normalize(-uDirLight.direction);
    float diff = diffuseLighting(normal,lightDir);
    float spec = specularLighting(normal,lightDir,viewDir,uDirLight.specularExponent);
    vec4 color = getColor();
    vec4 ambient = vec4(uDirLight.ambientColor,1.0) * color;
    vec4 diffuse = vec4(uDirLight.diffuseColor * diff,1.0) * color;
    vec4 specular = vec4(uDirLight.specularColor * spec,1.0) * vec4(0.5,0.5,1.0);
    return ambient + (diffuse + specular) * calcShadow(uDirLight.shadowMap,uDirLight.shadowVPMatrix * vPosition,uDirLight.shadowEnabled);
}

float calcAttenuation(PointLight pointLight,float distance){
    return 1.0 / (pointLight.constant + pointLight.linear * distance + pointLight.quadratic * (distance * distance));
}

vec4 calcPointLight(PointLight pointLight,vec3 normal,vec3 viewDir){
    vec3 d = pointLight.position - vec3(vPosition);
    vec3 lightDir = normalize(d);
    float diff = diffuseLighting(normal,pointLight.specularExponent);
    float distance = length(d);
    float attenuation = calcAttenuation(pointLight,distance);
    vec4 color = getColor();
    vec4 ambient = vec4(pointLight.ambientColor,1.0) * color;
    vec4 diffuse = vec4(pointLight.diffuseColor * diff,1.0) * color;
    vec4 specular = vec4(pointLight.specularColor * spec,1.0);
    ambient *= attenuation;
    diffuse *= attenuation;
    specular *= attenuation;
    return ambient + (diffuse + specular) * calcShadow(pointLight.shadowMap,pointLight.shadowVPMatrix * vPosition,pointLight.shadowEnabled);
}



void main() {
    vec3 normal = normalize(vnormal);
    vec3 viewDir = normalize(uViewPos - vec3(vPosition));
    vec4 result = vec4(0.0);
    if (uDirLight.on == 1){
        result = calcDirLight(normal,viewDir);
    }
    for (int i = 0; i < uNumPointLights; i++){
        if (uPointLights[i].on == 1){
            result += calcPointLight(uPointLights[i],normal,viewDir);
        }
    }
    gl_FragColor = result;
}

当我在我的设备上运行应用程序时,logcat 显示以下几行

2021-06-24 17:49:14.032 2061-2096/com.outofbound.rhinoengine I/AdrenoGLES-0: Build Config                     : S P 10.0.7 AArch64
2021-06-24 17:49:14.032 2061-2096/com.outofbound.rhinoengine I/AdrenoGLES-0: Driver Path                      : /vendor/lib64/egl/libGLESv2_adreno.so
2021-06-24 17:49:14.036 2061-2096/com.outofbound.rhinoengine I/AdrenoGLES-0: PFP: 0x016ee190,ME: 0x00000000
2021-06-24 17:49:14.040 2061-2061/com.outofbound.rhinoengine D/SurfaceView: UPDATE null,mIsCastMode = false
2021-06-24 17:49:14.074 2061-2102/com.outofbound.rhinoengine I/AdrenoGLES-0: ERROR: 0:101: 'viewDir' : undeclared identifier 
    ERROR: 0:101: 'specularLighting' : no matching overloaded function found 
    ERROR: 2 compilation errors.  No code generated.
2021-06-24 17:49:14.075 2061-2102/com.outofbound.rhinoengine I/AdrenoGLES-0: ERROR: 0:101: 'viewDir' : undeclared identifier 
    ERROR: 0:101: 'specularLighting' : no matching overloaded function found 
    ERROR: 2 compilation errors.  No code generated.
2021-06-24 17:49:15.316 2061-2085/com.outofbound.rhinoengine W/System: A resource Failed to call close.

但是如果我只是在 main() 函数中将 viewDir 重命名为 v

void main() {
        vec3 normal = normalize(vnormal);
        vec3 v = normalize(uViewPos - vec3(vPosition));
        vec4 result = vec4(0.0);
        if (uDirLight.on == 1){
            result = calcDirLight(normal,v);
        }
        for (int i = 0; i < uNumPointLights; i++){
            if (uPointLights[i].on == 1){
                result += calcPointLight(uPointLights[i],v);
            }
        }
        gl_FragColor = result;
    }

上面的错误消失了,但应用程序仍然无法运行,显示黑屏。 有什么提示吗?

解决方法

在我看来,viewDir 问题是一个驱动程序错误,试图内联您的代码时出错。

但是,您应该知道这不是 OpenGLES 2 标准的简单着色器。正如 Dpk 暗示的那样,您不能假设 OpenGLES2 具有高精度。

此外,您不能假设任何地方都有足够均匀的空间供您的着色器使用。尝试使用 glGetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS,&maxFragmentUniforms); 来查看支持的制服数量。允许设备低至 16 vec4s,但您的着色器使用 100s。

如果您不想担心 GLES2 的某些严格限制,我建议您考虑切换到 OpenGLES 3 或 3.1。如果您坚持使用 OpenGLES2,那么也许可以将着色器从字面上切回零(只返回一种颜色)并逐渐构建功能。

此外,请确保您正在检查着色器编译和链接以及所有 OpenGLES 调用的错误,这样可以节省大量时间。

,

试试

//#version 100    
//precision highp float;

precision mediump float;

试试这个 opengles20 可能不支持参数中的 INT 参见文档

float on;
//if (uDirLight.on == 1){
if (uDirLight.on == 1.0){
,

我认为该错误与uniform uniform PointLight uPointLights[MAX_NUM_POINT_LIGHTS]; 的数组有关。所以我解决了使用一个点光源

uniform PointLight uPointLight;

无论如何我会尝试定义多个 uniform PointLight uPointLightN; 与 0

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。