顶点着色器 glsl qt

时间:2021-05-08 07:26:13

标签: qt opengl glsl

我正在尝试使用 QOpenGLWindow 在 opengl 中通过纹理映射实现每顶点照明。但是渲染的对象是黑色的。如果我在片段着色器中做相同的纹理映射,它工作正常。

//Vertex Shader        
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
layout (location = 2) in vec3 tangent;
layout (location = 3) in vec3 bitangent;
layout (location = 4) in vec2 texCoords;

out vec4 afragColor;

vec3 fragPos;
out vec2 fragTexCoords;
mat3 TBN;

uniform sampler2D diffuseMap;
uniform sampler2D specularMap;
uniform sampler2D bumpMap;

vec3 calcAmbientLight(int idx, vec3 color, float ambient) {
    return ambient * color * vec3(ambientLight[idx].color);
}

vec3 calcDirectionalLight(int idx, vec3 normal, vec3 color, float diff, float spec) {
    vec3 lightDir = normalize(-vec3(directionalLight[idx].direction));
    vec3 viewDir = normalize(vec3(viewPos) - fragPos);
    vec3 reflectDir = reflect(-lightDir, normal);

    vec3 result = vec3(0.0f);
    result += diff * color * max(dot(normal, lightDir), 0.0f);
    result += spec * color * pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);

    return result * vec3(directionalLight[idx].color);
}

vec3 calcPointLight(int idx, vec3 normal, vec3 color, float diff, float spec) {
    vec3 lightDir = normalize(vec3(pointLight[idx].pos) - fragPos);
    vec3 viewDir = normalize(vec3(viewPos) - fragPos);
    vec3 reflectDir = reflect(-lightDir, normal);
    float dis = length(vec3(pointLight[idx].pos) - fragPos);

    vec3 result = vec3(0.0f);
    result += diff * color * max(dot(normal, lightDir), 0.0f);
    result += spec * color * pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);

    float attenuation = 1.0f / (pointLight[idx].attenuation[3]
                            + pointLight[idx].attenuation[2] * dis
                            + pointLight[idx].attenuation[1] * dis * dis);
    result *= attenuation * pointLight[idx].attenuation[0] + (1.0f - pointLight[idx].attenuation[0]);

    return result * vec3(pointLight[idx].color);
}

vec3 calcSpotLight(int idx, vec3 normal, vec3 color, float diff, float spec) {
    vec3 lightDir = normalize(vec3(spotLight[idx].pos) - fragPos);
    vec3 viewDir = normalize(vec3(viewPos) - fragPos);
    vec3 reflectDir = reflect(-lightDir, normal);
    float dis = length(vec3(spotLight[idx].pos) - fragPos);
    float theta = dot(lightDir, normalize(-vec3(spotLight[idx].direction)));
    float intensity = (theta - spotLight[idx].cutOff[1]) / (spotLight[idx].cutOff[0] - spotLight[idx].cutOff[1]);

    vec3 result = vec3(0.0f);
    result += diff * color * max(dot(normal, lightDir), 0.0f);
    result += spec * color * pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);

    float attenuation = 1.0f / (spotLight[idx].attenuation[3]
                            + spotLight[idx].attenuation[2] * dis
                            + spotLight[idx].attenuation[1] * dis * dis);
    result *= attenuation * spotLight[idx].attenuation[0] + (1.0f - spotLight[idx].attenuation[0]);

    return result * vec3(spotLight[idx].color) * clamp(intensity, 0.0f, 1.0f);
}


void main() {
    vec3 T = normalize(mat3(modelMat) * tangent);
    vec3 B = normalize(mat3(modelMat) * bitangent);
    vec3 N = normalize(mat3(normalMat) * normal);
    
    fragPos = vec3(modelMat * vec4(position, 1.0f));
    fragTexCoords = texCoords;
    TBN = mat3(T, B, N);

    mat4 MVP = projMat * viewMat * modelMat;

    vec3 color  = material.useDiffuseMap == 1 ? texture(diffuseMap, fragTexCoords).rgb : vec3(material.color);
    float spec  = material.useSpecularMap == 1 ? texture(specularMap, fragTexCoords).r : material.specular;
    vec3 normal = material.useBumpMap == 1 ? texture(bumpMap, fragTexCoords).rgb * 2 - 1 : vec3(0, 0, 1);
    normal = normalize(TBN * normalize(normal));

    afragColor = vec4(0, 0, 0, 1);

    for (int i = 0; i < ambientLightNum; i++)
        afragColor += vec4(calcAmbientLight(i, color, material.ambient), 1);

    for (int i = 0; i < directionalLightNum; i++)
        afragColor += vec4(calcDirectionalLight(i, normal, color, material.diffuse, spec), 1);

    for (int i = 0; i < pointLightNum; i++)
        afragColor += vec4(calcPointLight(i, normal, color, material.diffuse, spec), 1);

    for (int i = 0; i < spotLightNum; i++)
        afragColor += vec4(calcSpotLight(i, normal, color, material.diffuse, spec), 1);

    if (highlighted == 1)
        afragColor += vec4(0.2, 0.2, 0.2, 0);

    if (selected == 1)
        afragColor += vec4(0, 0, 0.4, 0);

    gl_Position = MVP * vec4(position, 1.0f);
    if (sizeFixed == 1) {
        float w = (MVP * vec4(0.0f, 0.0f, 0.0f, 1.0f)).w / 100;
        gl_Position = MVP * vec4(position * w, 1.0f);
    }
}






//Fragment Shader

out vec4 fragColor;

in vec4 afragColor;
void main() {
    fragColor = afragColor;

}

我觉得顶点着色器返回了一个非常暗的颜色,但也不做纹理映射。 谢谢

1 个答案:

答案 0 :(得分:1)

顶点着色器只是按顶点执行。因此,纹理仅查找图元的顶点(角)。顶点着色器的输出沿片段进行插值。您不能在顶点着色器中执行此算法。您需要在片段着色器中按片段执行此操作。
“Per Vertex Lighting”仅对恒定漫射光有意义。在镜面高光和纹理贴图的情况下,光分布不是线性的,不能用线性插值计算。 Per-vertex 光照仅用于非常简单的光照模型,目前一般不使用。