430 lines
No EOL
19 KiB
GLSL
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;
|
|
} |