learnopengl tutorial fragment shader for 2 points light - c++

I have been following www.learnopengl.com tutorial and tried to load models using the method described. It works until the very end where it asks you to load the nanosuit with 2 points lights. I have copied the exact code from the tutorial with: camera, mesh, model, and shader classes however the issue is with the fragment shader. If I try a simple one like:
#version 330 core
in vec2 TexCoords;
out vec4 color;
uniform sampler2D texture_diffuse1;
void main()
{
color = vec4(texture(texture_diffuse1, TexCoords));
}
, the model is loaded and the textures too. But if try the solution given for 2 points lighting the texture is black:
#version 330 core
struct Material {
sampler2D texture_diffuse1;
sampler2D texture_specular1;
float shininess;
};
/* Note: because we now use a material struct again you want to change your
mesh class to bind all the textures using material.texture_diffuseN instead of
texture_diffuseN. */
struct PointLight {
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 2
in vec3 fragPosition;
in vec3 Normal;
in vec2 TexCoords;
out vec4 color;
uniform vec3 viewPos;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform Material material;
// Function prototypes
vec3 CalcPointLight(PointLight light, Material mat, vec3 normal, vec3 fragPos, vec3 viewDir);
void main()
{
vec3 result;
vec3 viewDir = normalize(viewPos - fragPosition);
vec3 norm = normalize(Normal);
for(int i = 0; i < NR_POINT_LIGHTS; i++)
result += CalcPointLight(pointLights[i], material, norm, fragPosition, viewDir);
color = vec4(result, 1.0f);
}
// Calculates the color when using a point light.
vec3 CalcPointLight(PointLight light, Material mat, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
// Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), mat.shininess);
// Attenuation
float distance = length(light.position - fragPos);
float attenuation = 1.0f / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
// Combine results
vec3 ambient = light.ambient * vec3(texture(mat.texture_diffuse1, TexCoords));
vec3 diffuse = light.diffuse * diff * vec3(texture(mat.texture_diffuse1, TexCoords));
vec3 specular = light.specular * spec * vec3(texture(mat.texture_specular1, TexCoords));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
I also modified the mesh class as described in the fragment shader from:
glUniform1i(glGetUniformLocation(shader.Program, (name + number).c_str()), i);
to:
glUniform1i(glGetUniformLocation(shader.Program, ("material." + name + number).c_str()), i);
Is anyone having the same issue?

It seems like GLSL does not like function. If I take CalcPointLight() code and place it in main(), it works!
#version 330 core
struct Material {
sampler2D texture_diffuse1;
sampler2D texture_specular1;
float shininess;
};
/* Note: because we now use a material struct again you want to change your
mesh class to bind all the textures using material.texture_diffuseN instead of
texture_diffuseN. */
struct PointLight {
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 2
in vec3 fragPosition;
in vec3 Normal;
in vec2 TexCoords;
out vec4 color;
uniform vec3 viewPos;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform Material material;
void main()
{
vec3 result;
vec3 viewDir = normalize(viewPos - fragPosition);
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(pointLights[0].position - fragPosition);
// Diffuse shading
float diff = max(dot(norm, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// Attenuation
float distance = length(pointLights[0].position - fragPosition);
float attenuation = 1.0f / (pointLights[0].constant + pointLights[0].linear * distance + pointLights[0].quadratic * (distance * distance));
// Combine results
vec3 ambient = pointLights[0].ambient * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 diffuse = pointLights[0].diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 specular = pointLights[0].specular * spec * vec3(texture(material.texture_specular1, TexCoords));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
result = ambient+diffuse+specular;
color = vec4(result, 1.0f);
}
Edit: Found the answer there: GLSL sampler2D in struct. You can't instanciate a struct that contains an opaque type such as sampler2D.
Edit1: You can actually use those variables into a function without passing them as arguments since they are defined globally:
#version 330 core
struct Material {
sampler2D texture_diffuse1;
sampler2D texture_specular1;
float shininess;
};
/* Note: because we now use a material struct again you want to change your
mesh class to bind all the textures using material.texture_diffuseN instead of
texture_diffuseN. */
struct PointLight {
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
#define NR_POINT_LIGHTS 2
in vec3 fragPosition;
in vec3 Normal;
in vec2 TexCoords;
out vec4 color;
uniform vec3 viewPos;
uniform PointLight pointLights[NR_POINT_LIGHTS];
uniform Material material;
vec3 CalcLights(int i);
void main()
{
vec3 result;
for(int i=0; i<NR_POINT_LIGHTS; i++)
result += CalcLights(i);
color = vec4(result, 1.0f);
}
vec3 CalcLights(int i) //viewPos fragPosition pointLights[] Normal material TexCoords
{
vec3 viewDir = normalize(viewPos - fragPosition);
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(pointLights[i].position - fragPosition);
// Diffuse shading
float diff = max(dot(norm, lightDir), 0.0);
// Specular shading
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
// Attenuation
float distance = length(pointLights[i].position - fragPosition);
float attenuation = 1.0f / (pointLights[i].constant + pointLights[i].linear * distance + pointLights[i].quadratic * (distance * distance));
// Combine results
vec3 ambient = pointLights[0].ambient * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 diffuse = pointLights[0].diffuse * diff * vec3(texture(material.texture_diffuse1, TexCoords));
vec3 specular = pointLights[0].specular * spec * vec3(texture(material.texture_specular1, TexCoords));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient+diffuse+specular);
}

Related

GLSL having strange black faces with the second mesh

platform: Windows10
context: OpenGL, glew, Win32
So I loaded 2 meshes(using a simple OBJ parser, which only reads the triangulated mesh), with vertexpos,uv and normal data. The first mesh is lighted okay. No black faces.The second one looks like this.
The Strange Effects
my vertex shader:
#version 440
in vec3 pos;
in vec2 tex;
in vec3 nor;
uniform float Scale;
uniform mat4 perspective;
uniform mat4 model;
out vec3 normaldir;
out vec2 texOut;
out vec3 FragPos;
void main()
{
normaldir = normalize(mat3(transpose(inverse(model))) * nor);
gl_Position = perspective * model * vec4(pos.xyz, 1.0);
texOut = tex;
FragPos = vec3(model * vec4(pos, 1.0));
}
my fragment shader:
#version 440
uniform float Scale;
uniform sampler2D diffuse;
uniform sampler2D normal;
uniform vec3 viewPos;
//uniform sampler2D normalMap0;
in vec3 normaldir;
in vec2 texOut;
in vec3 FragPos;
layout(location = 0) out vec4 FragColor0;
void main()
{
vec3 lightPos = {2,6,0};
lightPos.x = sin(Scale)*5;
lightPos.z = cos(Scale)*5;
vec3 lightDir = normalize(lightPos - FragPos);
vec3 lightColor = {1.0,1.0,1.0};
float specularStrength = 1.6;
float diff = max(dot(normaldir, lightDir), 0.0);
vec3 diffuseD = diff * lightColor;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, normaldir);
vec3 ambient = {0.0,0.2,0.4};
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 25);
vec3 specular = specularStrength * spec * lightColor;
vec3 diffuseCol = texture(diffuse, texOut).xyz;
vec3 result = (ambient + diffuseD+ specular) * diffuseCol;
FragColor0 = vec4(result, 1.0);
}
Sorry I made a very dumb mistake. Thank you for all your support #Rabbid76 (Yes I did inverted the normals yes) #paddy
The problem was Binding the normal buffers. I bind glm::vec2 * size instead of glm::vec3 * size for normals' buffers

How to convert GLSL shaders to GLSL ES

I'm porting an openGL application to webassembly using Emscripten. I've written a bunch of shaders in GLSL (330) for the native version. However for the webversion I need shaders written in GLSL ES (300 es). How would I go about converting my shaders from GLSL to GLSL ES?
Possibilities I have considered so far:
GLSL -> SPIR-V -> GLSL ES,
having a bunch of #ifdef statements in the GLSL code in order to make blocks of code only execute for GLSL ES or GLSL,
writing custom C++ code that dynamically creates GLSL / GLSL ES code depending on what you need
simply having two nearly identical copies of all the shaders, one in GLSL and the other in GLSL ES
Example of GLSL vertex shader:
#version 330 core
#define NR_LIGHTS 10
layout (location = 0) in vec3 position;
layout (location = 1) in vec3 normal;
out vec3 normalViewSpace;
out vec3 posViewSpace;
out vec2 textureCoords;
out vec4 positionsLightSpace[NR_LIGHTS];
uniform mat4 modelMatrix;
uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
uniform mat4 lightMatrices[NR_LIGHTS];
void main()
{
vec4 posViewSpaceV4;
posViewSpaceV4 = viewMatrix * modelMatrix * vec4(position, 1.0);
posViewSpace = posViewSpaceV4.xyz;
gl_Position = projectionMatrix * posViewSpaceV4;
normalViewSpace = mat3(viewMatrix) * normalMatrix * normal;
for( int i = 0; i
Example of GLSL fragment shader:
#version 330 core
#define NR_LIGHTS 10
struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
float alpha;
};
struct Light {
vec3 posViewSpace;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
vec3 directionViewSpace;
float cutOff;
float outerCutOff;
sampler2D shadowMap;
};
out vec4 FragColor;
in vec3 normalViewSpace;
in vec3 posViewSpace;
in vec4 positionsLightSpace[NR_LIGHTS];
uniform Material material;
uniform Light lights[NR_LIGHTS];
float shadowCalculation(vec4 posLightSpace, sampler2D shadowMap, Light light)
{
// perform perspective divide
vec3 projCoords = posLightSpace.xyz / posLightSpace.w; // range [-1, 1]
// transform range [0, 1]
projCoords = projCoords * 0.5 + 0.5;
float closestDepth = texture(shadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
vec3 lightDir = normalize(light.posViewSpace - posViewSpace);
float bias = max(0.00005 * (1.0 - dot(normalViewSpace, lightDir)), 0.000005); // solves shadow acne
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
return shadow;
}
vec3 calcSpotLight( Light light, vec3 normal, vec3 position, float shadow) // normal and position in view space, although this function should not care about which space it's in
{
vec3 result = vec3(0.0, 0.0, 0.0);
vec3 lightDir = normalize(light.posViewSpace - position);
float theta = dot(lightDir, normalize(-light.directionViewSpace));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0, 1.0); // interpolate between inner and outer cutOff and clamp to 0 and 1
if( intensity > 0 ) // if inside spot radius
{
// attenuation
float distance = length(light.posViewSpace - position);
float attenuation = 1.0 / (light.constant + light.linear * distance + light.quadratic * (distance * distance));
if( attenuation > 0.001 )
{
// ambient
vec3 ambient = material.ambient * light.ambient;
// diffuse
vec3 norm = normalize(normalViewSpace);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * material.diffuse * light.diffuse;
// specular
vec3 viewDir = normalize(-position); // in view space the camera is at (0, 0, 0)
vec3 reflectDir = reflect(-lightDir, norm); // reflect function expect vector FROM light source TO position
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
vec3 specular = material.specular * spec * light.specular;
// result
result = intensity * attenuation * (ambient + (1.0 - shadow) * (diffuse + specular));
}
}
return result;
}
void main()
{
vec3 result = material.ambient * 0.08;
for( int i = 0; i

OpenGL geometry shader passing texture coordinates

I'm having issues with passing my texture coordinates correctly through a geometry shader. My texture coordinates getting all messed up when it ends up in my fragment shader.
Here's the vertex shader:
#version 330 core
layout(location = 0) in vec3 position;
layout(location = 1) in vec3 normal;
layout(location = 2) in vec2 texCoord;
out VS_OUT
{
vec3 v_Normal;
vec2 v_TexCoord;
vec3 v_FragPos;
} vs_out;
uniform mat4 u_Model;
uniform mat4 u_View;
uniform mat4 u_Projection;
void main()
{
gl_Position = u_Projection * u_View * u_Model * vec4(position, 1.0);
vs_out.v_Normal = normalize(mat3(transpose(inverse(u_Model))) * normal);
vs_out.v_TexCoord = texCoord;
vs_out.v_FragPos = vec3(u_Model * vec4(position, 1.0));
}
Geometry shader:
#version 330 core
layout(triangles) in;
layout(triangle_strip, max_vertices = 3) out;
in VS_OUT
{
vec3 v_Normal;
vec2 v_TexCoord;
vec3 v_FragPos;
} gs_in[];
out GS_OUT
{
vec3 v_Normal;
vec2 v_TexCoord;
vec3 v_FragPos;
} gs_out;
uniform float u_Time;
vec4 explode(vec4 position, vec3 normal)
{
float magnitude = 2.0;
vec3 direction = normal * ((sin(u_Time) + 1.0) / 2.0) * magnitude;
return position + vec4(direction, 0.0);
}
vec3 GetNormal()
{
vec3 a = vec3(gl_in[0].gl_Position) - vec3(gl_in[1].gl_Position);
vec3 b = vec3(gl_in[2].gl_Position) - vec3(gl_in[1].gl_Position);
return normalize(cross(a, b));
}
void main()
{
vec3 normal = GetNormal();
gl_Position = explode(gl_in[0].gl_Position, normal);
gs_out.v_Normal = gs_in[0].v_Normal;
gs_out.v_TexCoord = gs_in[0].v_TexCoord;
gs_out.v_FragPos = vec3(explode(vec4(gs_in[0].v_FragPos, 1.0), normal));
EmitVertex();
gl_Position = explode(gl_in[1].gl_Position, normal);
gs_out.v_Normal = gs_in[1].v_Normal;
gs_out.v_TexCoord = gs_in[1].v_TexCoord;
gs_out.v_FragPos = vec3(explode(vec4(gs_in[1].v_FragPos, 1.0), normal));
EmitVertex();
gl_Position = explode(gl_in[2].gl_Position, normal);
gs_out.v_Normal = gs_in[1].v_Normal;
gs_out.v_TexCoord = gs_in[1].v_TexCoord;
gs_out.v_FragPos = vec3(explode(vec4(gs_in[1].v_FragPos, 1.0), normal));
EmitVertex();
EndPrimitive();
}
Fragment shader:
#version 330 core
struct Material
{
sampler2D ambient;
sampler2D diffuse;
sampler2D specular;
sampler2D emissive;
float shininess;
};
struct DirectionalLight {
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
struct SpotLight {
vec3 position;
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
float cutOff;
float outerCutOff;
};
out vec4 color;
in GS_OUT
{
vec3 v_Normal;
vec2 v_TexCoord;
vec3 v_FragPos;
} fs_in;
#define NR_POINT_LIGHTS 1
uniform Material u_Material;
uniform DirectionalLight u_DirectionalLight;
uniform PointLight u_PointLights[NR_POINT_LIGHTS];
uniform SpotLight u_SpotLight;
uniform vec3 u_ViewPos;
uniform samplerCube skybox;
vec3 calculateDirectionalLight(DirectionalLight light, Material material, vec2 texCoord, vec3 normal, vec3 viewDirection);
vec3 calculatePointLight(PointLight light, Material material, vec2 texCoord, vec3 normal, vec3 fragPos, vec3 viewDirection);
vec3 calculateSpotLight(SpotLight light, Material material, vec2 texCoord, vec3 normal, vec3 fragPos, vec3 viewDirection);
void main()
{
vec3 lightColor = vec3(0.0);
vec3 normal = normalize(fs_in.v_Normal);
vec3 viewDirection = normalize(u_ViewPos - fs_in.v_FragPos);
lightColor += calculateDirectionalLight(u_DirectionalLight, u_Material, fs_in.v_TexCoord, normal, viewDirection);
for (int i = 0; i < NR_POINT_LIGHTS; i++)
lightColor += calculatePointLight(u_PointLights[i], u_Material, fs_in.v_TexCoord, normal, fs_in.v_FragPos, viewDirection);
lightColor += calculateSpotLight(u_SpotLight, u_Material, fs_in.v_TexCoord, normal, fs_in.v_FragPos, viewDirection);
lightColor += texture(u_Material.ambient, fs_in.v_TexCoord).rgb * texture(skybox, reflect(-viewDirection, normal)).rgb;
color = vec4(lightColor, 1.0);
}
vec3 calculateDirectionalLight(DirectionalLight light, Material material, vec2 texCoord, vec3 normal, vec3 viewDirection)
{
vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoord));
vec3 lightDirection = normalize(-light.direction);
vec3 diffuse = light.diffuse * vec3(texture(material.diffuse, texCoord)) * max(dot(lightDirection, normal), 0.0);
vec3 reflectDirection = reflect(-lightDirection, normal);
vec3 specular = light.specular * vec3(texture(material.specular, texCoord)) * pow(max(dot(viewDirection, reflectDirection), 0.0), material.shininess);
// vec3 emmisive = texture(material.emmisive, texCoord).rgb;
return vec3(ambient + diffuse + specular);
}
vec3 calculatePointLight(PointLight light, Material material, vec2 texCoord, vec3 normal, vec3 fragPos, vec3 viewDirection)
{
vec3 ambient = light.ambient * vec3(texture(material.diffuse, texCoord));
vec3 lightDirection = normalize(light.position - fragPos);
vec3 diffuse = light.diffuse * vec3(texture(material.diffuse, texCoord)) * max(dot(lightDirection, normal), 0.0);
vec3 reflectDirection = reflect(-lightDirection, normal);
vec3 specular = light.specular * vec3(texture(material.specular, texCoord)) * pow(max(dot(viewDirection, reflectDirection), 0.0), material.shininess);
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance +
light.quadratic * (distance * distance));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
// vec3 emmisive = texture(material.emmisive, texCoord).rgb;
return vec3(ambient + diffuse + specular);
}
vec3 calculateSpotLight(SpotLight light, Material material, vec2 texCoord, vec3 normal, vec3 fragPos, vec3 viewDirection)
{
vec3 lightDirection = normalize(light.position - fragPos);
float theta = dot(lightDirection, 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(texture(material.diffuse, texCoord));
vec3 diffuse = light.diffuse * vec3(texture(material.diffuse, texCoord)) * max(dot(lightDirection, normal), 0.0);
vec3 reflectDirection = reflect(-lightDirection, normal);
vec3 specular = light.specular * vec3(texture(material.specular, texCoord)) * pow(max(dot(viewDirection, reflectDirection), 0.0), material.shininess);
// vec3 emmisive = texture(material.emmisive, texCoord).rgb;
float distance = length(light.position - fragPos);
float attenuation = 1.0 / (light.constant + light.linear * distance +
light.quadratic * (distance * distance));
ambient *= intensity * attenuation;
diffuse *= intensity * attenuation;
specular *= intensity * attenuation;
return vec3(ambient + diffuse + specular);
}
Before I've added the geometry shader and passed the interpolated vertex attributes through it:
After passing varying attributes through the geometry shader:
Any ideas what I'm missing?
gl_Position = explode(gl_in[2].gl_Position, normal);
gs_out.v_Normal = gs_in[1].v_Normal;
gs_out.v_TexCoord = gs_in[1].v_TexCoord;
Looks like a copy paste error, you probably meant to put 2 here instead of 1.

Attenuation does not get applied correctly

I can't understand does the light attenuation correctly get applied or not.
It seems like it's not because the shininess of the steel frame for cube located at (-500, 100, 100)(at the left) is too much highlighted - must be less I think, considering that the light position (white cube) is (100.0, 100.0f, 100.0f).
I'm using this formula to get the attenuation
1.0 / (constant + linear * distance + quadratic * (distance^2))
Fragment shader:
#version 450 core
struct Material {
sampler2D diffuse;
sampler2D specular;
float shininess;
};
struct Light {
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float constant;
float linear;
float quadratic;
};
uniform vec3 cameraPosition;
uniform Material material;
uniform Light light;
in vec3 vNormal;
in vec2 vTexCoord;
in vec4 fragPosition;
out vec4 color;
void main() {
vec3 norm = vNormal;
vec3 lightDir = normalize(light.position - vec3(fragPosition.xyz));
vec3 viewDir = normalize(cameraPosition - vec3(fragPosition.xyz));
vec3 reflectDir = reflect(-lightDir, norm);
vec3 ambient = light.ambient * vec3(texture(material.diffuse, vTexCoord));
vec3 diffuse = light.diffuse * max(dot(norm, lightDir), 0.0) * vec3(texture(material.diffuse, vTexCoord));
vec3 specular = light.specular * pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess) * vec3(texture(material.specular, vTexCoord));
float d = length(lightDir);
float attenuation = 1.0f / (light.constant + light.linear * d + light.quadratic * (d * d));
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
color = vec4(ambient + diffuse + specular, 1.0f);
}
And passing the following values to the program
glUniform1f(lightConstantLoc, 1.0);
glUniform1f(lightLinearLoc, 0.1);
glUniform1f(lightQuadraticLoc, 0.01);
Also same positions but changed the view angle
So what's wrong there? Are my calculations wrong? What's going there?

Ambient and Specular lighting not working correctly in GLSL

In my lighting scene, for some reason the ambient lighting isn't working at all. The whole model is the same brightness, no matter which way it is facing. I tried getting rid of the attenuation but it still has the same results. Along with that, the specular lighting is always shining, no matter where the camera is. It is supposed to shine based on player position.
Here is a screenshot of the ambient problem: Imgur.com
As you can see, the part of the sphere that is facing away from the light (located at [0.0,4.0,0.0]) is the same color as the part facing the light. The ambient factor is supposed to be 0.2 of the fragment color.
Vertex shader source:
layout(location = 0) in vec3 positions;
layout(location = 1) in vec2 texCoords;
layout(location = 2) in vec3 normals;
out vec3 new_normal;
out vec3 worldPos_out;
out vec2 pass_texCoords;
struct Matrices {
mat4 projection;
mat4 worldMatrix;
mat4 modelMatrix;
mat3 normalMatrix;
};
uniform Matrices mat;
void main(void)
{
pass_texCoords = texCoords;
vec4 newPosition = vec4(positions, 1);
vec4 worldPos = (mat.modelMatrix * newPosition);
mat4 Camera = mat.projection * mat.worldMatrix;
gl_Position = (Camera * worldPos);
new_normal = mat.normalMatrix * normals;
worldPos_out = worldPos.xyz;
}
Fragment shader source:
in vec3 new_normal;
in vec3 worldPos_out;
in vec2 pass_texCoords;
out vec4 outColor;
uniform vec3 viewPos;
#define MAX_LIGHTS 50
struct Material {
sampler2D diffuseMap;
sampler2D specularMap;
vec3 specular;
float shininess;
};
uniform Material material;
struct Light {
vec3 position;
vec3 color;
vec3 ambient;
vec3 diffuse;
vec3 specular;
float radius;
};
uniform Light Lights[MAX_LIGHTS];
uniform int numLights;
struct Math {
float constant;
float linear;
float quadratic;
} math;
vec3 applyPointLight(Light light, vec3 normal, vec3 fragPos, vec3 viewDir, vec3 surfaceColor, vec3 surfaceSpecular) {
vec3 lightDir = normalize(light.position - fragPos);
//Diffuse shading
float diff = max(dot(normal, lightDir), 0.0);
//Specular shading
vec3 reflectDir = reflect(-lightDir, normal);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
//Attenuation
float distance = length(light.position - fragPos);
float attenuation = 5.0 / (math.constant + math.linear * distance +
math.quadratic * (distance * distance));
vec3 ambient = light.ambient * surfaceColor;
vec3 diffuse = light.diffuse * surfaceColor * light.color;
vec3 specular = light.specular * surfaceSpecular * light.color;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return (ambient + diffuse + specular);
}
void main(void) {
vec3 surfaceColor = vec3(texture(material.diffuseMap, pass_texCoords));
vec3 surfaceSpecular = vec3(texture(material.specularMap, pass_texCoords));
vec3 unitNormal = normalize(new_normal);
vec3 viewDir = normalize(viewPos - worldPos_out);
math.constant = 1.0;
math.linear = 0.09;
math.quadratic = 0.032;
vec3 linearColor;
for(int i = 0; i < numLights; i++)
linearColor += applyPointLight(Lights[i], unitNormal, worldPos_out, viewDir, surfaceColor, surfaceSpecular);
float gamma = 2.2;
vec3 fragColor;
fragColor.rgb = pow(linearColor.rgb, vec3(1.0/gamma));
outColor = vec4(linearColor, 1.0);
}
In your applyPointLight function, you're not using the diff and spec variables, which are presumably the light-dependent changes to diffuse and specular. See if the following works:
vec3 diffuse = light.diffuse * surfaceColor * light.color * diff;
vec3 specular = light.specular * surfaceSpecular * light.color * spec;