GLSL operands to arithmetic operators must be numeric - opengl

I have some old GLSL code that compiled fine previously, but after switching to Linux's gcc compiler it's suddenly throwing errors. From the fragement shader:
#version 330 core
out vec4 FragColor;
in vec2 TexCoord;
in vec3 Normal;
in vec3 FragPos;
// texture samplers
uniform sampler2D texture0;
uniform vec3 lightPos;
uniform vec3 viewPos;
uniform vec3 lightColor;
void main()
{
//ambient lighting
vec3 ambLig = vec3(1.0,1.0,1.0);
float ambientStrength = 0.15;
vec4 ambient = ambientStrength * vec4(ambLig,1.0);
//diffuse lighting
vec3 norm = normalize(Normal);
vec3 lightDir = normalize(lightPos - FragPos);
float diff = max(dot(norm, lightDir), 0.0);
vec3 diffuse = diff * lightColor;
//specular lighting
float specularStrength = 0.5;
vec3 viewDir = normalize(viewPos - FragPos);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = pow(max(dot(viewDir, reflectDir), 0.0), 32.0);
vec3 specular = specularStrength * spec * lightColor;
FragColor = texture(texture0, TexCoord) * (ambient + diffuse + specular);
}
This throws an error on the final line, where I calculate FragColor:
Using ALSA driver
ERROR::SHADER_COMPILATION_ERROR of type: FRAGMENT
0:37(45): error: vector size mismatch for arithmetic operator
0:37(45): error: operands to arithmetic operators must be numeric
0:37(14): error: operands to arithmetic operators must be numeric
I checked out some previous questions and it seems the problem occurs when using GLSL 1.2 or earlier, since it doesn't do automatic casts. But I have no idea what the problem could be here, since I'm using OPENGL Core 3.3, which should map to GLSL 3.30 Help me please.
Note: I've included a version of glad in the build with api specified as 3.3 for convenience. That could be the root of the problem, but I'm not sure, since I believe I build everything correctly.
EDIT: See answer below, also change
vec4 ambient = ambientStrength * vec4(ambLig,1.0);
to
vec3 ambient = ambientStrength * ambLig;

The return value of texture(texture0, TexCoord) is of type vec4. However, ambient + diffuse + specular is of type vec3.
Change:
FragColor = texture(texture0, TexCoord) * (ambient + diffuse + specular);
FragColor = texture(texture0, TexCoord) * vec4(ambient + diffuse + specular, 1.0);

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

Should I use a different shader for each light type in OpenGL renderer

I am making a relatively simple render for a physics engine (something similar to this). I am just learning OpenGL and have been following this tutorial. I want my renderer to be able to handle a small number of lights chosen from the types: directional, point, spotlight, and area light. Also I want simple shadows using shadow maps. So for example a scene might contain two spotlights or one directional light or one point light and one spotlight etc. Currently I have one larger shader that handles all the lights together, however now that I am experimenting with shadow maps it seems light it would be better (from a modular design perspective) to have a different shader for each light or at least each light type. I am wondering if this is a reasonable idea from the perspective of efficiency. To make this more concrete my current vertex looks like:
#version 130
in vec3 position;
in vec3 normal;
in vec2 atexture;
out vec3 FragPos;
out vec3 Normal;
out vec2 TexCoord;
out vec4 FragPosLightSpace;
uniform mat4 model;
uniform mat4 view;
uniform mat4 projection;
uniform mat4 lightView;
uniform mat4 lightProjection;
void main()
{
gl_Position = projection * view * model * vec4(position.x, position.y, position.z, 1.0);
FragPos = vec3(model * vec4(position, 1.0));
Normal = normalize(normal);
TexCoord = atexture;
FragPosLightSpace = lightProjection * lightView * vec4(FragPos, 1.0f);
}
and fragment shader:
#version 130
struct Material
{
float shininess;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct DirLight
{
vec3 direction;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct PointLight
{
vec3 position;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct SpotLight {
vec3 position;
vec3 direction;
float cutOff;
float outerCutOff;
float constant;
float linear;
float quadratic;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
struct AreaLight
{
vec3 position;
vec3 ambient;
vec3 diffuse;
vec3 specular;
};
out vec4 FragColor;
in vec3 FragPos;
in vec3 Normal;
in vec2 TexCoord;
in vec4 FragPosLightSpace;
uniform Material material;
uniform DirLight dirLight;
uniform PointLight pointLight;
uniform SpotLight spotLight;
uniform AreaLight areaLight;
uniform vec3 cameraPos;
uniform sampler2D texture1;
uniform sampler2D shadowMap;
float CalcShadow(vec4 FragPosLightSpace);
vec3 CalcDirLight(Material material, DirLight light, vec3 normal, vec3 viewDir);
vec3 CalcPointLight(Material material, PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcSpotLight(Material material, SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir);
vec3 CalcAreaLight(Material material, AreaLight light);
void main(void)
{
vec3 viewDir = normalize(cameraPos - FragPos);
vec3 finalLight = vec3(0.0f, 0.0f, 0.0f);
finalLight += CalcDirLight(material, dirLight, Normal, viewDir);
finalLight += CalcPointLight(material, pointLight, Normal, FragPos, viewDir);
finalLight += CalcSpotLight(material, spotLight, Normal, FragPos, viewDir);
finalLight += CalcAreaLight(material, areaLight);
FragColor = texture2D(texture1, TexCoord) * vec4(finalLight, 1.0f);
}
float CalcShadow(vec4 fragPosLightSpace)
{
// only actually needed when using perspective projection for the light
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
// projCoord is in [-1,1] range. Convert it ot [0,1] range.
projCoords = projCoords * 0.5 + 0.5;
float closestDepth = texture(shadowMap, projCoords.xy).r;
float currentDepth = projCoords.z;
float bias = 0.005f;
float shadow = currentDepth - bias > closestDepth ? 1.0 : 0.0;
return shadow;
}
vec3 CalcDirLight(Material material, DirLight light, vec3 normal, vec3 viewDir)
{
vec3 lightDir = normalize(-light.direction);
vec3 reflectDir = reflect(-lightDir, normal);
float ambientStrength = 1.0f;
float diffuseStrength = max(dot(normal, lightDir), 0.0);
float specularStrength = pow(max(dot(viewDir, reflectDir), 0.0), material.shininess);
float shadow = CalcShadow(FragPosLightSpace);
vec3 ambient = light.ambient * material.ambient * ambientStrength;
vec3 diffuse = (1.0f - shadow) * light.diffuse * material.diffuse * diffuseStrength;
vec3 specular = (1.0f - shadow) * light.specular * material.specular * specularStrength;
return (ambient + diffuse + specular);
}
vec3 CalcPointLight(Material material, PointLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
vec3 reflectDir = reflect(-lightDir, normal);
float ambientStrength = 1.0f;
float diffuseStrength = max(dot(normal, lightDir), 0.0);
float specularStrength = pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);
float attenuation = 1.0f / (1.0f + 0.01f*pow(length(light.position - fragPos), 2));
vec3 ambient = light.ambient * material.ambient * ambientStrength;
vec3 diffuse = light.diffuse * material.diffuse * diffuseStrength;
vec3 specular = light.specular * material.specular * specularStrength;
ambient *= attenuation;
diffuse *= attenuation;
specular *= attenuation;
return vec3(ambient + diffuse + specular);
}
vec3 CalcSpotLight(Material material, SpotLight light, vec3 normal, vec3 fragPos, vec3 viewDir)
{
vec3 lightDir = normalize(light.position - fragPos);
vec3 reflectDir = reflect(-lightDir, normal);
float ambientStrength = 0.05f;
float diffuseStrength = max(dot(normal, lightDir), 0.0);
float specularStrength = pow(max(dot(viewDir, reflectDir), 0.0f), material.shininess);
float attenuation = 1.0f / (1.0f + 0.01f*pow(length(light.position - fragPos), 2));
float theta = dot(lightDir, normalize(-light.direction));
float epsilon = light.cutOff - light.outerCutOff;
float intensity = clamp((theta - light.outerCutOff) / epsilon, 0.0f, 1.0f);
vec3 ambient = light.ambient * material.ambient * ambientStrength;
vec3 diffuse = light.diffuse * material.diffuse * diffuseStrength;
vec3 specular = light.specular * material.specular * specularStrength;
ambient *= attenuation * intensity;
diffuse *= attenuation * intensity;
specular *= attenuation * intensity;
return vec3(ambient + diffuse + specular);
}
vec3 CalcAreaLight(Material material, AreaLight light)
{
// return vec3(0.0f, 0.0f, 0.0f);
return vec3(2*material.ambient);
}
What I would like to do is separate each light type out to a different shader so instead of having one "ubershader" I would have a directionalLight shader and a spotlight shader etc. Is this a good idea? In particular I am worried that switching shaders multiple times for each render call might be expensive?
Your question is too broad and doesn't fit into SO format. However I will try to answer it, mostly because it is frequently asked by beginners to engine programming.
To manipulate different shader setups for lighting and shadowing you have got 2 standard practices:
"Uber-shader"
The idea behind this is that you have every possible case embedded into this shader. So for example, you want to be able to render up to 4 light sources (I am talking here of forward-rendering), so you insert a for loop with max number of lights, and then pass a uniform (number of lights in the scene) to tell the loop in the real time how many times to iterate. Then, if you enable the shadow pass, you also pass a uniform into the uber-shader to activate an "if" condition for shadow map sampling. As you already can see, this way is quite inefficient. You will end up with complex branching all over your shader, and will have to submit multiple uniforms during runtime to change the shader state. All this impacts performance and usability. Well, you can simplify this a little, by using OpenGL 4.0 subroutines. But generally speaking - don't do it.
Shader permutations
This is a quite industry common way and while it is more complex to design and setup such a system, it pays off on the long run. The idea is that you configure your shaders code, based on use case scenario in run-time, (or if you have offline shader compiler available,then you can even do this in compile time), so at the end you get a shader string contain the code for the specific rendering setup. For example, if your scene has 2 lights + shadows, and a material a renderable object uses diffuse and normal map, then you configure the shaders for that material to generate a code to handle 2 lights, shadow mapping , diffuse and normal maps sampling. It would take me too much time and space here to write in detail how to design and code such a system. But generally speaking, you write a sort of shader templates, full of pre-processor flags for different permutations. You inject pre-processor flags for specific permutation type, then compile shaders and shader program. In top-notch game engines like Unity3D and Unreal, all possible shader permutations are generated already in editor during authoring time. If you roll your own engine, just compose required permutation during runtime and throw that into shader compiler. With long shader strings you will notice a slight freeze during online compilation, but if you cache and then reuse already compiled permutations of the shader programs, you are going to be fine.
Bonus part
You can also, do that as you proposed - prebuild the different variations of shaders, which is effectively my number 2 approach. But your proposal is problematic, because if you wrap a single light rendering logic into separate program, that would mean in case of a scene with 2 light sources:
1 - Render the object with first light source.
2 - Render the object with second light source.
Compose two frames into final result. This already requires 3 render passes and takes you more to the direction of deferred shading, which is a quite advanced technique and not always what you need unless your plan is to develop an engine to deal with huge amounts of geometry and light sources.

learnopengl tutorial fragment shader for 2 points light

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);
}

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;