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?
Related
trying to implement shadow. I checked my depth texture on a quad, and it seems correct, but the shadow is not displaying. I check my shadow vertex and fragment shaders, and I believe I have done the light space transformation correctly.
Here are my code.
directional light source matrix setup:
//light source states
glm::vec3 Window::lightColor = glm::vec3(0.9f, 0.9f, 0.9f);
glm::vec3 Window::lightDir = glm::vec3(-1.f, -1.f, 0.f);
glm::mat4 Window::lightView = glm::lookAt(glm::vec3(0.f) - glm::normalize(lightDir) * 15.f, glm::vec3(0.0f), glm::vec3(0.f, 1.f, 0.f));
float Window::near_plane = 0.01f;
float Window::far_plane = 50.1f;
float camWidth = 10.f;
glm::mat4 Window::lightProj = glm::ortho(-10.f, 10.f, -10.f, 10.f, Window::near_plane, Window::far_plane);
glm::mat4 Window::lightProjView = lightProj * lightView;
shadow drawing logic:
void Renderer::drawWithShadow(Object* obj) {
//set shader uniforms
Shader* shader = shadowShader;
shader->bind();
shader->setUniformMat4("model", obj->model);
shader->setUniformMat4("projView", projView);
shader->setUniformVec3("viewPos", eyePos);
//need another projection matrix
shader->setUniformMat4("lightSpaceMatrix", shadowProjView);
glcheck(glActiveTexture(GL_TEXTURE0));
glcheck(glBindTexture(GL_TEXTURE_2D, textID));
//light uniforms
shader->setUniformVec3("directionalLightDir", directionalLightDir);
shader->setUniformVec3("lightColor", lightColor);
glcheck(glBindVertexArray(obj->vao));
for (auto i = 0; i < obj->meshList.size(); i++) {
Mesh* mesh = obj->meshList[i];
prepMaterial(mesh->material, shader);
glcheck(glDrawElements(GL_TRIANGLES, mesh->size, GL_UNSIGNED_INT, (GLvoid*)(sizeof(GLuint) * mesh->vertexOffset)));
}
}
vert and frag shaders to prepare shadow depth textures
//vertex shader
#version 330 core
layout (location = 0) in vec3 position;
uniform mat4 projView;
uniform mat4 model;
void main() {
gl_Position = projView * model * vec4(position, 1.0);
}
//fragment shader
#version 330 core
void main()
{
}
vert and frag shaders to draw shadows with Phong lighting
//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 {
vec4 fragPos;
vec3 normal;
vec2 texCoord;
vec4 fragPosLightSpace;
} vs_out;
uniform mat4 projView;
uniform mat4 model;
uniform mat4 lightSpaceMatrix;
void main()
{
vs_out.fragPos = model * vec4(position, 1.0);
vs_out.normal = transpose(inverse(mat3(model))) * normal;
vs_out.texCoord = texCoord;
vs_out.fragPosLightSpace = lightSpaceMatrix * vs_out.fragPos;
gl_Position = projView * vs_out.fragPos;
}
//fragment shader
#version 330 core
uniform vec3 viewPos; //just the eye pos
uniform vec3 diffuseFactor; //kd
uniform vec3 ambientColor; //ka
uniform vec3 specColor; //ks
uniform float specHighlight; //ns, the larger this value is, the more apparent the light dot on the surface
uniform float dissolve; //d
//lights
uniform vec3 directionalLightDir;
uniform vec3 pointLightPos;
uniform vec3 lightColor;
uniform sampler2D shadowMap;
//uniform sampler2DShadow shadowMap;
in VS_OUT {
vec4 fragPos;
vec3 normal;
vec2 texCoord;
vec4 fragPosLightSpace;
} fs_in;
out vec4 fragColor;
float ShadowCalculation(vec4 fragPosLightSpace)
{
vec3 projCoords = fragPosLightSpace.xyz / fragPosLightSpace.w;
vec2 shadowCoords;
shadowCoords.x = projCoords.x * 0.5 + 0.5;
shadowCoords.y = projCoords.y * 0.5 + 0.5;
float closestDepth = texture(shadowMap, shadowCoords).r;
float currentDepth = projCoords.z * 0.5 + 0.5;
float shadowValue = currentDepth + 0.00001 > closestDepth ? 1.0 : 0.0;
//if(currentDepth < 0.0)
//shadowValue = 0.0;
return shadowValue;
}
void main()
{
vec3 lightDir = normalize(-directionalLightDir);
vec3 norm = normalize(fs_in.normal);
//diffuse lighting
float diffStrength = max(dot(norm, lightDir), 0.0); // this calculates diffuse intensity based on angle
vec3 diffuse = lightColor * diffStrength * diffuseFactor;
//specular
vec3 viewDir = normalize(viewPos - fs_in.fragPos.xyz);
vec3 reflectDir = reflect(-lightDir, norm);
float spec = 0.0;
if(specHighlight > 0.0) { // if specHighlight is < 0, pow might produce undefined result if base is also 0
spec = pow(max(dot(viewDir, reflectDir), 0.0), specHighlight);
}
vec3 specular = spec * specColor * lightColor;
float shadow = ShadowCalculation(fs_in.fragPosLightSpace);
//float shadow = textureProj(shadowMap, fs_in.fragPosLightSpace);
//vec3 result = ambientColor * 0.05 * lightColor + (diffuse + specular)*(1-shadow);
vec3 result = (diffuse + specular)*(1.0 - shadow);
fragColor = vec4(result, 1);
}
with just Phong shading, the scene looks like this:
Phong shading
when the scene is seen from the light source as depth value:
depth texture on quad
when I finally render the scene, it is mostly black; I made sure the far plane covers all of the bunnies:
render shadow
I am implementing a basic phong lighting GLSL shader; I have looked up some things on the internet, and found that the phong effect was created by adding an ambient, diffuse, and specular layer on the object (see image below, from tom dalling's site); problem is I have seen a lot of examples, and none of them really suits my GLSL set-up. Can any of you give me a code example of the correct way to implement the phong effect which would fit my GLSL set-up ? :
PS : This question could be put on hold because of the fact that it may be based on user opinion : In my mind, it is not, because I would like to know the most effective, and better way of implementing it.
Here is my vertex shader :
#version 120
uniform mat4 modelView;
uniform mat4 MVP;
uniform float time;
attribute vec3 position;
attribute vec2 texCoord;
attribute vec3 normal;
varying vec3 position0;
varying vec2 texCoord0;
varying vec3 normal0;
varying mat4 modelView0;
void main()
{
//Updating varyings...
position0 = position;
texCoord0 = texCoord;
normal0 = (MVP * vec4(normal, 0.0)).xyz;
modelView0 = modelView;
//set position
gl_Position = MVP * vec4(position, 1.0);
}
and my fragment shader :
#version 120
varying vec3 position0;
varying vec2 texCoord0;
varying vec3 normal0;
varying mat4 modelView0;
uniform sampler2D diffuse;
void main()
{
vec4 surfaceColor = texture2D(diffuse, texCoord0);
gl_FragColor = (texture2D(diffuse, texCoord0))
* clamp(dot(-vec3(0.0, 0.5, 0.5), normal0), 0, 1.0);
}
try this:
void main()
{
vec4 texread = texture2D(diffuse, texCoord0);
vec3 normal = normalize(normal0);
vec3 material_kd = vec3(1.0,1.0,1.0);
vec3 material_ks = vec3(1.0,1.0,1.0);
vec3 material_ka = vec3(0.2,0.2,0.2);
vec3 material_ke = vec3(0.0,0.0,0.0);
float material_shininess = 60;
vec3 lightpos = vec3(0.0,10.0,5.0);
vec3 lightcolor = vec3(1.0,1.0,1.0);
vec3 lightdir = normalize(lightpos - worldPosition);
float shade = clamp(dot(lightdir, normal), 0.0, 1.0);
vec3 toWorldpos = normalize((worldPosition) - u_eyePos);
vec3 reflectDir = reflect( toWorldpos, normal );
vec4 specular = vec4(pow(clamp(dot(lightdir, reflectDir),0.0,1.0), material_shininess) * lightcolor * material_ks, 1.0);
vec4 shaded = texread * vec4(material_kd, 1.0) * vec4(lightcolor , 1.0) * shade;
vec4 ambient = texread * vec4(material_ka, 1.0);
vec4 emission = vec4(material_ke, 1.0);
gl_FragColor = shaded + specular + emission + ambient;
}
it may have some compilation errors though as i didnt run it...
you may need to upload your eye position as a uniform (u_eyePos), and calculate the worldposition (worldPosition) for it to work
I made my own sphong shader : here is the code :
fragment shader :
#version 150
uniform mat4 modelView;
uniform mat3 normalMatrix;
uniform vec3 cameraPosition;
uniform sampler2D materialTex;
uniform float materialShininess;
uniform vec3 materialSpecularColor;
uniform vec3 lightPosition;//light settings
uniform vec3 lightIntensities;
uniform float lightAttenuation;
uniform float lightAmbientCoeff;
in vec3 position0;
in vec2 texCoord0;
in vec3 normal0;
out vec4 fragmentColor;
void main()
{
//calculate normal in world coordinates
vec3 normal = normalize(normalMatrix * normal0);
//calculate the location of this fragment (pixel) in world coordinates
vec3 surfacePos = vec3(modelView * vec4(position0, 1));
//color of the current fragment
vec4 surfaceColor = texture(materialTex, texCoord0);
//calculate the vector from this pixels surface to the light source
vec3 surfaceToLight = normalize(lightPosition - surfacePos);
//cam distance
vec3 surfaceToCamera = normalize(cameraPosition - surfacePos);
///////////////////////////DIFUSE///////////////////////////////////////
//calculate the cosine of the angle of incidence
//float diffuseCoeff = dot(normal, surfaceToLight) / (length(surfaceToLight) * length(normal));
float diffuseCoeff = max(0.0, dot(normal, surfaceToLight));
vec3 diffuse = diffuseCoeff * surfaceColor.rgb * lightIntensities;
/////////////////////////AMBIENT////////////////////////////////////////
vec3 ambient = lightAmbientCoeff * surfaceColor.rgb * lightIntensities;
/////////////////////////SPECULAR//////////////////////////////////////
float specularCoeff = 0.0;
if(diffuseCoeff > 0.0)
specularCoeff = pow(max(0.0, dot(surfaceToCamera, reflect(-surfaceToLight, normal))), materialShininess);
vec3 specular = specularCoeff * materialSpecularColor * lightIntensities;
////////////////////////ATTENUATION///////////////////////////////////
float distanceToLight = length(lightPosition - surfacePos);
float attenuation = 1.0 / (1.0 + lightAttenuation * pow(distanceToLight, 2));
/////////////////////////////////FINAL/////////////////////////////////
vec3 linearColor = ambient + attenuation * (diffuse + specular);
//finalColor with gamma correction
vec3 gamma = vec3(1.0/2.2);
fragmentColor = vec4(pow(linearColor, gamma), surfaceColor.a);
//fragmentColor = vec4(diffuseCoeff * lightIntensities * surfaceColor.rgb, surfaceColor.a);
}
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