1
votes

i am trying to achieve per vertex lighting with texture mapping in opengl using QOpenGLWindow. But the rendered object has black color. if i do same texture mapping in fragment shader, it works fine.

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

}

I feel the like the vertex shader returns a very dark color but also does not do texture mapping. Thank you

1
Why do you try to do this in the vertex shader when it works dine in the fragment shader? The vertex shader is just executed per vertex. Therefore, the texture is only looked up for the vertices (corners) of the primitives. The output of the vertex shader is interpolated along the fragments. You cannot do this algorithm in the vertex shader. You need to do it per fragment, in the fragment shader.Rabbid76
i am doing it to achieve per vertex lighting, so can't we texture mapping in vertex shader. if not then how we do texture mapping in vertex shader?Klaffy
You have to do the texture mapping in the fragment shader. You cannot do it in the vertex shader. Why do you want to do "per vertex lighting"? The quality of "per vertex lighting" is poor and the specular highlights are lost. "per vertex lighting" makes only sens for a constant diffuse light.Rabbid76
thank you, but in per vertex lighting do we normally calculate light in vertex shader and do texture mapping in fragment shader ?Klaffy
"per vertex lighting" makes only sens for a constant diffuse light. For specular hightlighs and texture mapping you'll need a fragment shader. Per-vertex lighting is only used for very simple light models and is generally not used these days.Rabbid76

1 Answers

1
votes

The vertex shader is just executed per vertex. Therefore, the texture is only looked up for the vertices (corners) of the primitives. The output of the vertex shader is interpolated along the fragments. You cannot do this algorithm in the vertex shader. You need to do it per fragment, in the fragment shader.
"Per Vertex Lighting" only makes sense for a constant diffuse light. In the case of specular highlights and texture maps, the light distribution is not linear and cannot be calculated with linear interpolation. Per-vertex lighting is only used for very simple light models and is generally not used these days.