CGII/framework/shader/cgv_gl/glsl/lighting.glsl
2018-05-17 16:01:02 +02:00

430 lines
No EOL
19 KiB
GLSL

#version 150 compatibility
uniform bool local_viewer = false;
uniform int lights_enabled[gl_MaxLights]; // tells about the state of the lights (whether they are enabled or not)
/**
* Computes the lighting calculations for a directional light.
*
* \param lightSource the light source for which to do the lighting
* \param lightModelProduct the light product for the light source
* \param normal the surface normal for the fragment
* \param ambient the ambient factor in which to write the new ambient factor
* \param diffuse the diffuse factor in which to write the new diffuse factor
* \param specular the specular factor in which to write the new specular factor
*/
void computeDirectionalLight(in gl_LightSourceParameters lightSource,
in gl_LightProducts lightProduct,
in vec3 normal,
inout vec4 ambient,
inout vec4 diffuse,
inout vec4 specular)
{
float diffuseFactor = max(dot(normal, normalize(vec3(lightSource.position))), 0.0);
float specularFactor = 0.0;
if (diffuseFactor > 0.0)
{
specularFactor = max(dot(normal, vec3(lightSource.halfVector)), 0.0);
specularFactor = pow(specularFactor, gl_FrontMaterial.shininess);
}
ambient += lightProduct.ambient;
diffuse += lightSource.diffuse * diffuseFactor;
specular += lightProduct.specular * specularFactor;
}
/**
* Computes the lighting calculations for a directional light in the Phong illumination modell.
*
* \param lightSource the light source for which to do the lighting
* \param lightModelProduct the light product for the light source
* \param normal the surface normal for the fragment
* \param ambient the ambient factor in which to write the new ambient factor
* \param diffuse the diffuse factor in which to write the new diffuse factor
* \param specular the specular factor in which to write the new specular factor
*/
void computeDirectionalLightPhong(in gl_LightSourceParameters lightSource,
in gl_LightProducts lightProduct,
in vec3 viewVector,
in vec3 normal,
inout vec4 ambient,
inout vec4 diffuse,
inout vec4 specular)
{
vec3 lightVector = normalize(vec3(lightSource.position));
float diffuseFactor = max(dot(normal, lightVector), 0.0);
float specularFactor = 0.0;
if (diffuseFactor > 0.0)
{
vec3 reflectVector = 2.0*dot(normal,lightVector)*normal - lightVector;
specularFactor = max(dot(reflectVector, viewVector), 0.0);
specularFactor = pow(specularFactor, gl_FrontMaterial.shininess);
}
ambient += lightProduct.ambient;
diffuse += lightSource.diffuse * diffuseFactor;
specular += lightProduct.specular * specularFactor;
}
/**
* Computes the lighting calculations for a point light.
*
* \param lightSource the light source for which to do the lighting
* \param lightModelProduct the light product for the light source
* \param viewVector the viewing vector
* \param position the position of the fragment in eye coordinate space
* \param normal the surface normal for the fragment
* \param ambient the ambient factor in which to write the new ambient factor
* \param diffuse the diffuse factor in which to write the new diffuse factor
* \param specular the specular factor in which to write the new specular factor
*/
void computePointLight(in gl_LightSourceParameters lightSource,
in gl_LightProducts lightProduct,
in vec3 viewVector,
in vec3 position,
in vec3 normal,
inout vec4 ambient,
inout vec4 diffuse,
inout vec4 specular)
{
vec3 lightVec = lightSource.position.xyz / lightSource.position.w - position; // vector from fragment to light source
float distance = length(lightVec); // distance between surface and light position
lightVec = normalize(lightVec);
// attenuation factor
float attenuation = 1.0 / (lightSource.constantAttenuation +
lightSource.linearAttenuation * distance +
lightSource.quadraticAttenuation * distance * distance);
float diffuseFactor = max(dot(normal, lightVec), 0.0);
float specularFactor = 0.0;
if (diffuseFactor > 0.0)
{
vec3 halfVector = normalize(lightVec + viewVector);
specularFactor = max(dot(normal, halfVector), 0.0);
specularFactor = pow(specularFactor, gl_FrontMaterial.shininess);
}
ambient += lightProduct.ambient * attenuation;
diffuse += lightSource.diffuse * diffuseFactor * attenuation;
specular += lightProduct.specular * specularFactor * attenuation;
}
/**
* Computes the lighting calculations for a point light.
*
* \param lightSource the light source for which to do the lighting
* \param lightModelProduct the light product for the light source
* \param viewVector the viewing vector
* \param position the position of the fragment in eye coordinate space
* \param normal the surface normal for the fragment
* \param ambient the ambient factor in which to write the new ambient factor
* \param diffuse the diffuse factor in which to write the new diffuse factor
* \param specular the specular factor in which to write the new specular factor
*/
void computePointLightPhong(in gl_LightSourceParameters lightSource,
in gl_LightProducts lightProduct,
in vec3 viewVector,
in vec3 position,
in vec3 normal,
inout vec4 ambient,
inout vec4 diffuse,
inout vec4 specular)
{
vec3 lightVec = lightSource.position.xyz / lightSource.position.w - position; // vector from fragment to light source
float distance = length(lightVec); // distance between surface and light position
lightVec = normalize(lightVec);
// attenuation factor
float attenuation = 1.0 / (lightSource.constantAttenuation +
lightSource.linearAttenuation * distance +
lightSource.quadraticAttenuation * distance * distance);
float diffuseFactor = max(dot(normal, lightVec), 0.0);
float specularFactor = 0.0;
if (diffuseFactor > 0.0)
{
vec3 reflectVector = 2.0*dot(normal,lightVec)*normal - lightVec;
specularFactor = max(dot(reflectVector, viewVector), 0.0);
specularFactor = pow(specularFactor, gl_FrontMaterial.shininess);
}
ambient += lightProduct.ambient * attenuation;
diffuse += lightSource.diffuse * diffuseFactor * attenuation;
specular += lightProduct.specular * specularFactor * attenuation;
}
/**
* Computes the lighting calculations for a spot light.
*
* \param lightSource the light source for which to do the lighting
* \param lightModelProduct the light product for the light source
* \param viewVector the viewing vector
* \param position the position of the fragment in eye coordinate space
* \param normal the surface normal for the fragment
* \param ambient the ambient factor in which to write the new ambient factor
* \param diffuse the diffuse factor in which to write the new diffuse factor
* \param specular the specular factor in which to write the new specular factor
*/
void computeSpotLight(in gl_LightSourceParameters lightSource,
in gl_LightProducts lightProduct,
in vec3 viewVector,
in vec3 position,
in vec3 normal,
inout vec4 ambient,
inout vec4 diffuse,
inout vec4 specular)
{
vec3 lightVec = lightSource.position.xyz / lightSource.position.w - position; // vector from fragment to light source
float distance = length(lightVec); // distance between surface and light position
lightVec = normalize(lightVec);
// see if point on surface is inside cone of illumination
float spotDot = dot(-lightVec, normalize(lightSource.spotDirection));
if (spotDot >= lightSource.spotCosCutoff)
{ // light adds contribution
// attenuation factor
float attenuation = 1.0 / (lightSource.constantAttenuation +
lightSource.linearAttenuation * distance +
lightSource.quadraticAttenuation * distance * distance);
// combine the spotlight and distance attenuation
if (lightSource.spotExponent != 0.0)
attenuation *= pow(spotDot, lightSource.spotExponent);
float diffuseFactor = max(0.0, dot(normal, lightVec));
float specularFactor = 0.0;
if (diffuseFactor > 0.0)
{
vec3 halfVector = normalize(lightVec + viewVector);
specularFactor = max(0.0, dot(normal, halfVector));
specularFactor = pow(specularFactor, gl_FrontMaterial.shininess);
}
ambient += lightProduct.ambient * attenuation;
diffuse += lightSource.diffuse * diffuseFactor * attenuation;
specular += lightProduct.specular * specularFactor * attenuation;
}
}
/**
* Computes the lighting calculations for a spot light.
*
* \param lightSource the light source for which to do the lighting
* \param lightModelProduct the light product for the light source
* \param viewVector the viewing vector
* \param position the position of the fragment in eye coordinate space
* \param normal the surface normal for the fragment
* \param ambient the ambient factor in which to write the new ambient factor
* \param diffuse the diffuse factor in which to write the new diffuse factor
* \param specular the specular factor in which to write the new specular factor
*/
void computeSpotLightPhong(in gl_LightSourceParameters lightSource,
in gl_LightProducts lightProduct,
in vec3 viewVector,
in vec3 position,
in vec3 normal,
inout vec4 ambient,
inout vec4 diffuse,
inout vec4 specular)
{
vec3 lightVec = lightSource.position.xyz / lightSource.position.w - position; // vector from fragment to light source
float distance = length(lightVec); // distance between surface and light position
lightVec = normalize(lightVec);
// see if point on surface is inside cone of illumination
float spotDot = dot(-lightVec, normalize(lightSource.spotDirection));
if (spotDot >= lightSource.spotCosCutoff)
{ // light adds contribution
// attenuation factor
float attenuation = 1.0 / (lightSource.constantAttenuation +
lightSource.linearAttenuation * distance +
lightSource.quadraticAttenuation * distance * distance);
// combine the spotlight and distance attenuation
if (lightSource.spotExponent != 0.0)
attenuation *= pow(spotDot, lightSource.spotExponent);
float diffuseFactor = max(0.0, dot(normal, lightVec));
float specularFactor = 0.0;
if (diffuseFactor > 0.0)
{
vec3 reflectVector = 2.0*dot(normal,lightVec)*normal - lightVec;
specularFactor = max(dot(reflectVector, viewVector), 0.0);
specularFactor = pow(specularFactor, gl_FrontMaterial.shininess);
}
ambient += lightProduct.ambient * attenuation;
diffuse += lightSource.diffuse * diffuseFactor * attenuation;
specular += lightProduct.specular * specularFactor * attenuation;
}
}
/**
* Does the lighting calculation.
*
* \param position the position of the fragment in eye coordinates
* \param normal the normal of the fragment in eye coordinates
* \param diffuseMaterial the diffuse material color
* \return the fragment color resulting from illumination computations
*/
vec4 doTwoSidedLighting(vec3 position, vec3 normal, vec4 diffuseMaterial, int side)
{
// http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
normal = normalize(normal); // if GL_NORMALIZE is enabled (Page 217); makes no sense here
// normal = normal * gl_NormalScale; // if GL_RESCALE_NORMAL is enabled (Page 217); makes no sense here
// http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
vec3 viewVector = vec3(0.0, 0.0, 1.0); // not local viewer
if (local_viewer)
viewVector = -normalize(position); // if GL_LIGHT_MODEL_LOCAL_VIEWER is set to != 0 (Page 222)
vec4 ambient = vec4(0.0); // ambient color (variant 1) / factor (variant 2)
vec4 diffuse = vec4(0.0); // diffuse color (variant 1) / factor (variant 2)
vec4 specular = vec4(0.0); // specular color (variant 1) / factor (variant 2)
for (int i = 0; i < gl_MaxLights; i++)
{
//if (enabled[i] == 1)
if (lights_enabled[i] == 1)
{
if (gl_LightSource[i].position.w == 0.0)
computeDirectionalLight(gl_LightSource[i], side == 1 ? gl_FrontLightProduct[i] : gl_BackLightProduct[i], normal, ambient, diffuse, specular);
else if (gl_LightSource[i].spotCutoff == 180.0)
computePointLight(gl_LightSource[i], side == 1 ? gl_FrontLightProduct[i] : gl_BackLightProduct[i], viewVector, position, normal, ambient, diffuse, specular);
else
computeSpotLight(gl_LightSource[i], side == 1 ? gl_FrontLightProduct[i] : gl_BackLightProduct[i], viewVector, position, normal, ambient, diffuse, specular);
}
}
// sceneColor = Ecm + Acm * Acs
// 'Ecm' == gl_FrontMaterial.emission
// 'Acm' == gl_FrontMaterial.ambient
// 'Acs' = ambient color of scene (set through 'glLightModelfv(GL_LIGHT_MODEL_AMBIENT, sceneAmbient);')
return (side == 1 ? gl_FrontLightModelProduct.sceneColor : gl_BackLightModelProduct.sceneColor) + ambient + diffuseMaterial * diffuse + specular;
}
/**
* Does the lighting calculation.
*
* \param position the position of the fragment in eye coordinates
* \param normal the normal of the fragment in eye coordinates
* \param diffuseMaterial the diffuse material color
* \return the fragment color resulting from illumination computations
*/
vec4 doLightingAmb(vec3 position, vec3 normal, vec4 ambientMaterial, vec4 diffuseMaterial)
{
// http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
normal = normalize(normal); // if GL_NORMALIZE is enabled (Page 217); makes no sense here
// normal = normal * gl_NormalScale; // if GL_RESCALE_NORMAL is enabled (Page 217); makes no sense here
// http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
vec3 viewVector = vec3(0.0, 0.0, 1.0); // not local viewer
if (local_viewer)
viewVector = -normalize(position); // if GL_LIGHT_MODEL_LOCAL_VIEWER is set to != 0 (Page 222)
vec4 ambient = vec4(0.0); // ambient color (variant 1) / factor (variant 2)
vec4 diffuse = vec4(0.0); // diffuse color (variant 1) / factor (variant 2)
vec4 specular = vec4(0.0); // specular color (variant 1) / factor (variant 2)
for (int i = 0; i < gl_MaxLights; i++)
{
//if (enabled[i] == 1)
if (lights_enabled[i] == 1)
{
if (gl_LightSource[i].position.w == 0.0)
computeDirectionalLight(gl_LightSource[i], gl_FrontLightProduct[i], normal, ambient, diffuse, specular);
else if (gl_LightSource[i].spotCutoff == 180.0)
computePointLight(gl_LightSource[i], gl_FrontLightProduct[i], viewVector, position, normal, ambient, diffuse, specular);
else
computeSpotLight(gl_LightSource[i], gl_FrontLightProduct[i], viewVector, position, normal, ambient, diffuse, specular);
}
}
// sceneColor = Ecm + Acm * Acs
// 'Ecm' == gl_FrontMaterial.emission
// 'Acm' == gl_FrontMaterial.ambient
// 'Acs' = ambient color of scene (set through 'glLightModelfv(GL_LIGHT_MODEL_AMBIENT, sceneAmbient);')
return gl_FrontLightModelProduct.sceneColor + ambientMaterial * ambient + diffuseMaterial * diffuse + specular;
}
vec4 doLighting(vec3 position, vec3 normal, vec4 diffuseMaterial)
{
// http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
normal = normalize(normal); // if GL_NORMALIZE is enabled (Page 217); makes no sense here
// normal = normal * gl_NormalScale; // if GL_RESCALE_NORMAL is enabled (Page 217); makes no sense here
// http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
vec3 viewVector = vec3(0.0, 0.0, 1.0); // not local viewer
if (local_viewer)
viewVector = -normalize(position); // if GL_LIGHT_MODEL_LOCAL_VIEWER is set to != 0 (Page 222)
vec4 ambient = vec4(0.0); // ambient color (variant 1) / factor (variant 2)
vec4 diffuse = vec4(0.0); // diffuse color (variant 1) / factor (variant 2)
vec4 specular = vec4(0.0); // specular color (variant 1) / factor (variant 2)
for (int i = 0; i < gl_MaxLights; i++)
{
//if (enabled[i] == 1)
if (lights_enabled[i] == 1)
{
if (gl_LightSource[i].position.w == 0.0)
computeDirectionalLight(gl_LightSource[i], gl_FrontLightProduct[i], normal, ambient, diffuse, specular);
else if (gl_LightSource[i].spotCutoff == 180.0)
computePointLight(gl_LightSource[i], gl_FrontLightProduct[i], viewVector, position, normal, ambient, diffuse, specular);
else
computeSpotLight(gl_LightSource[i], gl_FrontLightProduct[i], viewVector, position, normal, ambient, diffuse, specular);
}
}
// sceneColor = Ecm + Acm * Acs
// 'Ecm' == gl_FrontMaterial.emission
// 'Acm' == gl_FrontMaterial.ambient
// 'Acs' = ambient color of scene (set through 'glLightModelfv(GL_LIGHT_MODEL_AMBIENT, sceneAmbient);')
return gl_FrontLightModelProduct.sceneColor + ambient + diffuseMaterial * diffuse + specular;
}
/**
* Does the lighting calculation with the Phong Illumination model.
*
* \param position the position of the fragment in eye coordinates
* \param normal the normal of the fragment in eye coordinates
* \param diffuseMaterial the diffuse material color
* \return the fragment color resulting from illumination computations
*/
vec4 doPhongLighting(vec3 position, vec3 normal, vec4 diffuseMaterial)
{
// http://www.opengl.org/sdk/docs/man/xhtml/glNormal.xml
normal = normalize(normal); // if GL_NORMALIZE is enabled (Page 217); makes no sense here
// normal = normal * gl_NormalScale; // if GL_RESCALE_NORMAL is enabled (Page 217); makes no sense here
// http://www.opengl.org/sdk/docs/man/xhtml/glLightModel.xml
vec3 viewVector = vec3(0.0, 0.0, 1.0); // not local viewer
if (local_viewer)
viewVector = -normalize(position); // if GL_LIGHT_MODEL_LOCAL_VIEWER is set to != 0 (Page 222)
vec4 ambient = vec4(0.0); // ambient color (variant 1) / factor (variant 2)
vec4 diffuse = vec4(0.0); // diffuse color (variant 1) / factor (variant 2)
vec4 specular = vec4(0.0); // specular color (variant 1) / factor (variant 2)
for (int i = 0; i < gl_MaxLights; i++)
{
//if (enabled[i] == 1)
if (lights_enabled[i] == 1)
{
if (gl_LightSource[i].position.w == 0.0)
computeDirectionalLightPhong(gl_LightSource[i], gl_FrontLightProduct[i], viewVector, normal, ambient, diffuse, specular);
else if (gl_LightSource[i].spotCutoff == 180.0)
computePointLightPhong(gl_LightSource[i], gl_FrontLightProduct[i], viewVector, position, normal, ambient, diffuse, specular);
else
computeSpotLightPhong(gl_LightSource[i], gl_FrontLightProduct[i], viewVector, position, normal, ambient, diffuse, specular);
}
}
// sceneColor = Ecm + Acm * Acs
// 'Ecm' == gl_FrontMaterial.emission
// 'Acm' == gl_FrontMaterial.ambient
// 'Acs' = ambient color of scene (set through 'glLightModelfv(GL_LIGHT_MODEL_AMBIENT, sceneAmbient);')
return gl_FrontLightModelProduct.sceneColor + ambient + diffuseMaterial * diffuse + specular;
}