i have a c++ opengl app - i import a model using assimp, and i try to render it, and it renders correctly, but the shader seems to be wrong as it is displayed as black, and it shouldnt.
here is my vertex shader:
#version 330 

uniform mat4 P;
uniform mat4 V;
uniform mat4 M;
uniform sampler2D tex1s;
uniform sampler2D tex2s;
uniform mat4 modelMatrix;

in vec3 vertex;
in vec2 texCoords;
in vec3 normal;
in vec3 tangent;
in vec3 bitangent;

out vec3 fragPos;
out vec2 texCoordsOut;
out vec3 normalOut;
out vec3 tangentOut;
out vec3 bitangentOut;

void main(){ 	
	fragPos = vec3(M * vec4(vertex, 1.0));
	normalOut = vec3(transpose(inverse(M))) * normal;
	texCoordsOut = texCoords;
	tangentOut = vec3(transpose(inverse(M))) * tangent;
	bitangentOut = vec3(transpose(inverse(M))) * bitangent;	
	gl_Position =  P * V * M * vec4(fragPos, 1.0);
}
here is my fragment shader:
#version 330

uniform vec3 diffuseColor;
uniform float shininess;
uniform vec3 emissiveColor;
uniform float opacity;
uniform sampler2D tex1s;
uniform sampler2D tex2s;
uniform vec3 lightColor;
uniform vec3 lightDirection;

in vec3 normalOut;
in vec3 fragPos;
in vec2 texCoordsOut; 
in vec3 tangentOut;
in vec3 bitangentOut;
out vec4 Color; 


void main() {
	vec3 normaln = normalize(normalOut);
    vec3 bitangentn = normalize(bitangentOut);
    vec3 tangentn = normalize(tangentOut);


    vec3 normalMap = texture(tex1s, texCoordsOut).rgb;
    normalMap = normalize(normalMap * 2.0 - 1.0);
    mat3 TBN = mat3(tangentn, bitangentn, normaln);
    vec3 transformedNormal = normalize(TBN * normalMap);

    // Diffuse Lighting
    float diffuseFactor = max(dot(transformedNormal, -lightDirection), 0.0);
    vec4 texColor = texture(tex2s, texCoordsOut);
    vec3 diffuse = diffuseColor * texColor.rgb * lightColor * diffuseFactor;

    // Emissive Lighting
    vec3 emissive = emissiveColor;

    // Final Color Calculation
    vec3 finalColor = diffuse + emissive;

    // shininess is between 0 and 256
    float specularFactor = pow(max(dot(transformedNormal, -lightDirection), 0.0), shininess);
    vec3 specular = vec3(1.0, 1.0, 1.0) * specularFactor;
    finalColor += specular;

    // Apply opacity
    finalColor *= opacity;

    Color = vec4(finalColor, 1.0);
}
here are relevant bits of my main code:
void buffers() {
	

	glGenVertexArrays(1, &vao);
	glBindVertexArray(vao);

	glGenBuffers(1, &vbo);
	glBindBuffer(GL_ARRAY_BUFFER, vbo);
	glBufferData(GL_ARRAY_BUFFER, meshData.vertices.size() * sizeof(glm::vec3), (& meshData.vertices[0]), GL_STATIC_DRAW);
	glVertexAttribPointer(sp->a("vertex"), 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(sp->a("vertex"));

	glGenBuffers(1, &nbo);
	glBindBuffer(GL_ARRAY_BUFFER, nbo);
	glBufferData(GL_ARRAY_BUFFER, meshData.normals.size() * sizeof(glm::vec3), (& meshData.normals[0]), GL_STATIC_DRAW);

	glVertexAttribPointer(sp->a("normal"), 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(sp->a("normal"));

	glGenBuffers(1, &tbo);
	glBindBuffer(GL_ARRAY_BUFFER, tbo);
	glBufferData(GL_ARRAY_BUFFER, meshData.textureCoords.size() * sizeof(glm::vec2), (& meshData.textureCoords[0]), GL_STATIC_DRAW);

	glVertexAttribPointer(sp->a("texCoords"), 2, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(sp->a("texCoords"));

	glGenBuffers(1, &tangentbo);
	glBindBuffer(GL_ARRAY_BUFFER, tangentbo);
	glBufferData(GL_ARRAY_BUFFER, meshData.tangents.size() * sizeof(glm::vec3), (& meshData.tangents[0]), GL_STATIC_DRAW);

	glVertexAttribPointer(sp->a("tangent"), 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(sp->a("tangent"));

	glGenBuffers(1, &bitangentbo);
	glBindBuffer(GL_ARRAY_BUFFER, bitangentbo);
	glBufferData(GL_ARRAY_BUFFER, meshData.bitangents.size() * sizeof(glm::vec3), (& meshData.bitangents[0]), GL_STATIC_DRAW);

	glVertexAttribPointer(sp->a("bitangent"), 3, GL_FLOAT, GL_FALSE, 0, 0);
	glEnableVertexAttribArray(sp->a("bitangent"));

	glGenBuffers(1, &ebo);
	glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
	glBufferData(GL_ELEMENT_ARRAY_BUFFER, meshData.indices.size() * sizeof(unsigned int), (& meshData.indices[0]), GL_STATIC_DRAW);




	glBindVertexArray(0);
}
void drawScene(GLFWwindow* window,float angle_x,float angle_y, float time) {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glm::mat4 V=glm::lookAt(
         glm::vec3(0.0, 2.0, 4.0),
         glm::vec3(0,0,0),
         glm::vec3(0.0f,1.0f,0.0f)); //Wylicz macierz widoku

	glm::mat4 P = glm::perspective(glm::radians(45.0f), aspectRatio, 0.1f, 50.0f); //Wylicz macierz rzutowania

    glm::mat4 M=glm::mat4(1.0f);
    sp->use();//Aktywacja programu cieniującego
	
	glActiveTexture(GL_TEXTURE0);
	tex1 = readTexture("./skeleton/skeleton_image1.png");
	glBindTexture(GL_TEXTURE_2D, tex1);
	glUniform1i(sp->u("tex1s"), 0);

	glActiveTexture(GL_TEXTURE1);
	tex2 = readTexture("./skeleton/skeleton_image0.png");
	glBindTexture(GL_TEXTURE_2D, tex2);
	glUniform1i(sp->u("tex2s"), 1);




	glUniformMatrix4fv(sp->u("P"), 1, false, glm::value_ptr(P));
	glUniformMatrix4fv(sp->u("V"), 1, false, glm::value_ptr(V));
	glUniformMatrix4fv(sp->u("M"), 1, false, glm::value_ptr(M));
	glUniformMatrix3fv(sp->u("diffuseColor"), 1, false, glm::value_ptr(allMaterialData[0].diffuseColors));
	glUniformMatrix3fv(sp->u("emissiveColor"), 1, false, glm::value_ptr(allMaterialData[0].emissiveColors));
	glUniform1f(sp->u("shininess"), allMaterialData[0].shininessValues);
	glUniform1f(sp->u("opacity"), allMaterialData[0].opacities);


	glUniform3f(sp->u("lightDirection"), 0.0f, 1.0f, 0.0f);
	glUniform3f(sp->u("lightColor"), 0.2f, 0.5f, 0.7f);


	//not done yet - figure out bones and then apply animations to them

	glBindVertexArray(vao);
	glDrawElements(GL_TRIANGLES, meshData.indices.size(), GL_UNSIGNED_INT, 0);
	glBindVertexArray(0);
    glfwSwapBuffers(window); //Przerzuć tylny bufor na przedni
}