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.
Related
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);
}
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;
I was trying to add a normal map effect to a shader tutorial I have found here but with no luck.
UPDATE 1:
I updated the code adding a tangent space matrix
Vertex shader:
#version 330
in vec3 inPosition;
in vec3 vertNormal;
in vec2 vertTexCoord;
in vec4 vertNormalMapping;
out vec3 fragVert;
out vec3 fragNormal;
out vec2 fragTexCoord;
out vec4 fragNormalMapping;
out mat3 TBNMatrix;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 camera;
void main(){
vec3 tangent;
vec3 binormal;
vec3 c1 = cross( vertNormal, vec3(0.0, 0.0, 1.0) );
vec3 c2 = cross( vertNormal, vec3(0.0, 1.0, 0.0) );
if( length(c1)>length(c2) )
{
tangent = c1;
}
else
{
tangent = c2;
}
tangent = normalize(tangent);
binormal = cross(vertNormal, tangent);
binormal = normalize(binormal);
mat3 normalMatrix = transpose(inverse(mat3(camera * modelViewProjectionMatrix )));
vec3 n = normalize(normalMatrix * vertNormal);
vec3 t = normalize(normalMatrix * tangent.xyz);
vec3 b = normalize(normalMatrix * binormal.xyz);
TBNMatrix = mat3(t, b, n);
fragTexCoord = vertTexCoord;
fragNormal = vertNormal;
fragVert = inPosition;
fragNormalMapping = vertNormalMapping;
gl_Position = camera * modelViewProjectionMatrix * vec4(inPosition, 1.0);
}
Fragment shader
#version 330
precision highp float;
uniform vec3 cameraPosition;
uniform mat4 modelViewProjectionMatrix;
uniform mat4 camera;
uniform sampler2D tex;
uniform sampler2D heightMap;
uniform float materialShininess;
uniform vec3 materialSpecularColor;
uniform struct Light {
vec3 position;
vec3 intensities; //a.k.a the color of the light
float attenuation;
float ambientCoefficient;
} light;
in vec3 fragNormal;
in vec3 fragVert;
in vec2 fragTexCoord;
in vec4 fragNormalMapping;
in mat3 TBNMatrix;
out vec4 finalColor;
void main() {
vec3 surfacePos = vec3(modelViewProjectionMatrix * vec4(fragVert, 1));
vec4 surfaceColor = texture(tex, fragTexCoord);
vec3 surfaceToLight = TBNMatrix * (light.position - surfacePos) ;
vec3 surfaceToCamera = TBNMatrix * (cameraPosition - surfacePos);
vec3 normal = normalize(texture(heightMap, fragTexCoord).xyz * 2.0 - 1.0);
//ambient
vec3 ambient = light.ambientCoefficient * surfaceColor.rgb * light.intensities;
//diffuse
float diffuseCoefficient = max(0.0, dot(normal, surfaceToLight));
vec3 diffuse = diffuseCoefficient * surfaceColor.rgb * light.intensities;
//specular
float specularCoefficient = 0.0;
if(diffuseCoefficient > 0.0)
specularCoefficient = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), materialShininess);
vec3 specular = specularCoefficient * materialSpecularColor * light.intensities;
//attenuation
float distanceToLight = length(light.position - surfacePos);
float attenuation = 1.0 / (1.0 + light.attenuation * pow(distanceToLight, 2));
//linear color (color before gamma correction)
vec3 linearColor = ambient + attenuation*(diffuse + specular);
//final color (after gamma correction)
vec3 gamma = vec3(1.0/2.2);
finalColor = vec4(pow(linearColor, gamma), surfaceColor.a);
}
The result is better but now the lighting is calculated wrong O.O
//OLD
I have tried with a blank color texture and a correct normal map texture and the result is this: The normal map is calculated correctly but... these lines are not so cool to see :-(
Any idea of what is the cause? thank you everyone for the help =D
posting here for clarity...
mv = camera * transform;//modelview
mvp = proj * camera * transform;//modelviewprojection
mvi = transpose(inverse(mv))//modelview inverse (=gl_NormalMatrix)
so you should have in place of modelViewProjectionMatrix passed to the shader the modelView and the projection separately, and compute the resulting mvp in the vertex shader.
(or precompute them all on cpu side)
Is anyone know why for shaders like...
Vertex.shader:
#version 330 core
layout(location = 0) in vec3 vertexPosition;
layout(location = 1) in vec3 vertexNormal;
layout(location = 2) in vec2 vertexTexcoord;
out vec3 gouraud;
out vec2 texcoord;
uniform mat4 pMatrix; // projection matrix
uniform mat4 vMatrix; // view matrix
uniform mat4 mMatrix; // model matrix
uniform mat3 nMatrix; // mMatrix -> inverted and transposed
#define NUM_LIGHTS 32
struct Light {
vec3 ambient;
vec3 diffuse;
vec3 specular;
vec4 position; // w == 0 -> directional
vec4 attenuation;
};
uniform Light lights[NUM_LIGHTS];
struct Material {
vec3 ambient;
vec3 diffuse;
vec3 specular;
float shininess;
};
uniform Material material;
void main() {
vec4 position = vec4(vertexPosition, 1.0);
vec3 vertex = vec3(mMatrix * position); // vertex in model space
vec3 normal = normalize(nMatrix * vertexNormal); // normal in model space
vec3 finalColor = vec3(0.0, 0.0, 0.0); // phong result
for(int i = 0; i < NUM_LIGHTS; ++i) {
if(lights[i].position.w == 0.0) { // directional light
vec3 lightDirection = normalize(lights[i].position.xyz);
vec3 N = normalize(normal); // normalize because normal will be interpolated (possible not unit vector)
vec3 E = normalize(-vertex);
vec3 R = normalize(-reflect(lightDirection, N));
finalColor += lights[i].ambient; // * material.ambient; // ambient
float lambert = max(dot(N, lightDirection), 0.0);
if(lambert > 0.0) {
finalColor += lights[i].diffuse * material.diffuse * lambert; // diffuse
float specular = pow(max(0.0, dot(reflect(-lightDirection, N), E)), material.shininess);
finalColor += lights[i].specular * material.specular * clamp(specular, 0.0, 1.0); // specular
}
}
else { // point light
vec3 lightDirection = lights[i].position.xyz - vertex;
float lightDistance = length(lightDirection);
lightDirection = normalize(lightDirection);
float attenuation = 1.0;
if(lights[i].attenuation[0] != 0.0) { // attenuation based on light radius
attenuation = smoothstep(lights[i].attenuation[0], 0.0, lightDistance);
}
else { // attenuation based on distance
attenuation = clamp(1.0 /
(lights[i].attenuation[1] +
lights[i].attenuation[2] * lightDistance +
lights[i].attenuation[3] * pow(lightDistance, 2)), 0.0, 1.0);
}
finalColor += lights[i].ambient * material.ambient;
vec3 N = normalize(normal); // normalize because normal will be interpolated (possible not unit vector)
float lambert = max(dot(N, lightDirection), 0.0);
if(lambert > 0.0) {
finalColor += lights[i].diffuse * material.diffuse * lambert * attenuation; // diffuse
vec3 E = normalize(-vertex);
vec3 R = normalize(-reflect(lightDirection, N));
float specular = pow(max(0.0, dot(reflect(-lightDirection, N), E)), material.shininess);
finalColor += lights[i].specular * material.specular * clamp(specular, 0.0, 1.0) * attenuation; // specular
}
}
}
gouraud = finalColor;
texcoord = vertexTexcoord;
gl_Position = pMatrix * vMatrix * mMatrix * position;
}
Fragment.shader:
#version 330 core
in vec3 gouraud;
in vec2 texcoord;
out vec3 color;
uniform sampler2D diffuseMap;
void main() {
color = gouraud * texture(diffuseMap, texcoord).rgb;
}
Runned on nVidia GeForce 8600GT and nVidia 710m the result is?
error C5060: out can't be used with non-varying color
But it's running on intel hd 2500..
Problem is only with nVidia.
Help :<
Update: full shader
I've been trying to update some code to be OpenGL 3.2 compliant, but I'm having trouble with my shaders. I've been reading up on the differences online, and my shaders compile, but my screen remains my glClearColor. I have a vertex and fragment shader (doing phong shading). Everything works great under OpenGL 2.1 / GLSL 1.2, the problems only arise under OpenGL 3.2 / GLSL 1.5
Here are my version 1.2 shaders:
Vertex:
#version 120
uniform mat4 uProjMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uModelMatrix;
uniform mat4 uNormalMatrix;
attribute vec3 aPosition;
attribute vec3 aNormal;
varying vec3 vWorldPosition;
varying vec3 vNormal;
void main() {
// Transforms
vec4 lPosition = uModelMatrix * vec4(aPosition.x, aPosition.y, aPosition.z, 1);
vWorldPosition = vec3(lPosition.x, lPosition.y, lPosition.z);
gl_Position = uProjMatrix * uViewMatrix * lPosition;
// Calculate the relative normal
vec4 lNormal = vec4(aNormal.x, aNormal.y, aNormal.z, 0);
lNormal = uNormalMatrix * lNormal;
vNormal = vec3(lNormal.x, lNormal.y, lNormal.z);
}
Fragment:
#version 120
struct Light {
vec3 position, color;
float constFalloff, linearFalloff, squareFalloff;
};
struct Material {
vec3 ambient, diffuse, specular, emission;
float shininess;
};
uniform Light uLights[10];
uniform int uNumLights;
uniform Material uMaterial;
uniform vec3 uCameraPos;
varying vec3 vWorldPosition;
varying vec3 vNormal;
void main() {
vec3 lNormal = normalize(vNormal);
vec3 finalColor = vec3(0.0, 0.0, 0.0);
for(int i = 0; i < uNumLights; ++i) {
// Diffuse light
vec3 toLight = uLights[i].position - vWorldPosition;
float lightDistance = length(toLight);
toLight = normalize(toLight);
float diffuseAmount = max(dot(lNormal, toLight), 0.0);
// Specular light
vec3 toCamera = normalize(uCameraPos - vWorldPosition);
vec3 reflection = normalize(2.0 * dot(toLight, lNormal) * lNormal - toLight);
float specularAmount = pow(max(dot(toCamera, reflection), 0.0), uMaterial.shininess);
// Falloff
float falloff = 1.0 / (uLights[i].constFalloff
+ uLights[i].linearFalloff * lightDistance
+ uLights[i].squareFalloff * lightDistance * lightDistance);
finalColor += ((uMaterial.diffuse * diffuseAmount
+ uMaterial.specular * specularAmount) * falloff
+ uMaterial.ambient) * uLights[i].color;
}
finalColor += uMaterial.emission;
gl_FragColor = vec4(finalColor.r, finalColor.g, finalColor.b, 1.0);
}
And my version 1.5 shaders:
Vertex:
#version 150 core
uniform mat4 uProjMatrix;
uniform mat4 uViewMatrix;
uniform mat4 uModelMatrix;
uniform mat4 uNormalMatrix;
in vec3 aPosition;
in vec3 aNormal;
out vec3 vWorldPosition;
out vec3 vNormal;
void main() {
// Transforms
vec4 lPosition = uModelMatrix * vec4(aPosition.x, aPosition.y, aPosition.z, 1);
vWorldPosition = vec3(lPosition.x, lPosition.y, lPosition.z);
gl_Position = uProjMatrix * uViewMatrix * lPosition;
// Calculate the relative normal
vec4 lNormal = vec4(aNormal.x, aNormal.y, aNormal.z, 0);
lNormal = uNormalMatrix * lNormal;
vNormal = vec3(lNormal.x, lNormal.y, lNormal.z);
}
Fragment:
#version 150 core
struct Light {
vec3 position, color;
float constFalloff, linearFalloff, squareFalloff;
};
struct Material {
vec3 ambient, diffuse, specular, emission;
float shininess;
};
uniform Light uLights[10];
uniform int uNumLights;
uniform Material uMaterial;
uniform vec3 uCameraPos;
in vec3 vWorldPosition;
in vec3 vNormal;
out vec4 outColor;
void main() {
vec3 lNormal = normalize(vNormal);
vec3 finalColor = vec3(0.0, 0.0, 0.0);
for(int i = 0; i < uNumLights; ++i) {
// Diffuse light
vec3 toLight = uLights[i].position - vWorldPosition;
float lightDistance = length(toLight);
toLight = normalize(toLight);
float diffuseAmount = max(dot(lNormal, toLight), 0.0);
// Specular light
vec3 toCamera = normalize(uCameraPos - vWorldPosition);
vec3 reflection = normalize(2.0 * dot(toLight, lNormal) * lNormal - toLight);
float specularAmount = pow(max(dot(toCamera, reflection), 0.0), uMaterial.shininess);
// Falloff
float falloff = 1.0 / (uLights[i].constFalloff
+ uLights[i].linearFalloff * lightDistance
+ uLights[i].squareFalloff * lightDistance * lightDistance);
finalColor += ((uMaterial.diffuse * diffuseAmount
+ uMaterial.specular * specularAmount) * falloff
+ uMaterial.ambient) * uLights[i].color;
}
finalColor += uMaterial.emission;
outColor = vec4(finalColor.r, finalColor.g, finalColor.b, 1.0);
}
I do not get any errors from compiling / linking the 1.5 shaders, but nothing draws. What am I missing?