mirror of
https://github.com/OpenFOAM/ThirdParty-6.git
synced 2025-12-08 06:57:43 +00:00
190 lines
5.6 KiB
GLSL
190 lines
5.6 KiB
GLSL
//=========================================================================
|
|
//
|
|
// Program: ParaView
|
|
// Module: vtkPVLightingHelper_s.glsl
|
|
//
|
|
// Copyright (c) Kitware, Inc.
|
|
// All rights reserved.
|
|
// See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details.
|
|
//
|
|
// This software is distributed WITHOUT ANY WARRANTY; without even
|
|
// the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
|
// PURPOSE. See the above copyright notice for more information.
|
|
//
|
|
//=========================================================================
|
|
// Filename: vtkPVLighting.glsl
|
|
// Filename is useful when using gldb-gui
|
|
|
|
// This file defines some lighting functions.
|
|
// They can be used either in a vertex or fragment shader.
|
|
|
|
// It is intented to be used in conjunction with vtkPVLightsSwitches class.
|
|
|
|
// Those functions expect uniform variables about the status of lights
|
|
// 1. In fixed-mode pipeline (glUseProgram(0)),
|
|
// 2. get the values with GLboolean lightSwitch[i]=glIsEnabled(GL_LIGHTi);
|
|
// 3. Switch to programmable pipeline (glUseProgram(prog))
|
|
// 4. Send boolean as uniform: var=glGetUniformLocation(prog,"lightSwitch[i]");
|
|
// 5. glUniform1i(var,lightSwitch[i]);
|
|
|
|
// vtkPVLightsSwitches class can do that for you.
|
|
|
|
|
|
// Example in vertex shader:
|
|
// Reminder: two-sided/one-sided is controlled by GL_VERTEX_PROGRAM_TWO_SIDE
|
|
//
|
|
// vec4 eyeCoords=gl_ModelViewMatrix*gl_Vertex;
|
|
// vec4 n=gl_Normalmatrix*gl_Normal;
|
|
// n=normalize(n);
|
|
// separateSpecularColor(gl_FrontMaterial,eyeCoords,n,gl_FrontColor,gl_FrontSecondaryColor);
|
|
// If two-sided.
|
|
// separateSpecularColor(gl_BackMaterial,eyeCoords,n,gl_BackColor,gl_BackSecondaryColor);
|
|
|
|
// Typical:
|
|
// gl_FrontColor=singleColor(gl_FrontMaterial,eyeCoords,n);
|
|
|
|
// This is convenience method to use in shader but you better do
|
|
// this computation on the CPU and send the result as a uniform.
|
|
|
|
// True if any enabled light is a positional one.
|
|
bool needSurfacePositionInEyeCoordinates()
|
|
{
|
|
bool result=false;
|
|
for (int i=0; !result && (i < gl_MaxLights); i++)
|
|
{
|
|
result = (gl_LightSource[i].diffuse.w != 0.0) &&
|
|
(gl_LightSource[i].position.w != 0.0);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
// Lighting computation based on a material m,
|
|
// a position on the surface expressed in eye coordinate (typically a vertex
|
|
// position in a vertex shader, something interpolated in a fragment shader),
|
|
// a unit normal `n' to the surface in eye coordinates.
|
|
// Most of the components are in cpri (primary color), the specular
|
|
// component is in csec (secondary color).
|
|
// Useful for blending color and textures.
|
|
void separateSpecularColor(gl_MaterialParameters m,
|
|
vec3 surfacePosEyeCoords,
|
|
vec3 n,
|
|
out vec4 cpri,
|
|
out vec4 csec)
|
|
{
|
|
cpri = m.emission + m.ambient * gl_LightModel.ambient; // ecm+acm*acs
|
|
csec = vec4(0.0,0.0,0.0,1.0);
|
|
vec3 wReverseRayDir = surfacePosEyeCoords;
|
|
|
|
// For each light,
|
|
for (int i=0; i < gl_MaxLights; i++)
|
|
{
|
|
// Trick.
|
|
bool lightEnabled = (gl_LightSource[i].diffuse.w != 0.0);
|
|
if (!lightEnabled)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
vec3 lightPos;
|
|
vec3 ldir;
|
|
vec3 h;
|
|
float att;
|
|
float spot;
|
|
float shininessFactor;
|
|
|
|
if (gl_LightSource[i].position.w != 0.0)
|
|
{
|
|
// ldir=light direction
|
|
ldir = lightPos - surfacePosEyeCoords;
|
|
float sqrDistance = dot(ldir,ldir);
|
|
ldir = normalize(ldir);
|
|
h = normalize(ldir + wReverseRayDir);
|
|
att = 1.0 / (gl_LightSource[i].constantAttenuation + gl_LightSource[i].linearAttenuation *
|
|
sqrt(sqrDistance) + gl_LightSource[i].quadraticAttenuation * sqrDistance);
|
|
}
|
|
else
|
|
{
|
|
att = 1.0;
|
|
ldir = gl_LightSource[i].position.xyz;
|
|
ldir = normalize(ldir);
|
|
h = normalize(ldir + wReverseRayDir);
|
|
}
|
|
|
|
if (att>0.0)
|
|
{
|
|
if (gl_LightSource[i].spotCutoff == 180.0)
|
|
{
|
|
spot = 1.0;
|
|
}
|
|
else
|
|
{
|
|
float coef=-dot(ldir,gl_LightSource[i].spotDirection);
|
|
if (coef>=gl_LightSource[i].spotCosCutoff)
|
|
{
|
|
spot=pow(coef,gl_LightSource[i].spotExponent);
|
|
}
|
|
else
|
|
{
|
|
spot=0.0;
|
|
}
|
|
}
|
|
if (spot>0.0)
|
|
{
|
|
// LIT operation...
|
|
float nDotL=dot(n,ldir);
|
|
float nDotH=dot(n,h);
|
|
|
|
// separate nDotL and nDotH for two-sided shading, otherwise we
|
|
// get black spots.
|
|
|
|
if (nDotL<0.0) // two-sided shading
|
|
{
|
|
nDotL=-nDotL;
|
|
}
|
|
|
|
if (nDotH<0.0) // two-sided shading
|
|
{
|
|
nDotH=-nDotH;
|
|
}
|
|
// ambient term for this light
|
|
vec4 cpril=m.ambient*gl_LightSource[i].ambient;// acm*adi
|
|
|
|
// diffuse term for this light
|
|
if (nDotL>0.0)
|
|
{
|
|
cpril+=m.diffuse*gl_LightSource[i].diffuse*nDotL; // dcm*dcli
|
|
}
|
|
|
|
// specular term for this light
|
|
shininessFactor=pow(nDotH,m.shininess); // srm
|
|
|
|
cpri+=att*spot*cpril;
|
|
|
|
// scm*scli
|
|
csec+=att*spot*
|
|
m.specular*gl_LightSource[i].specular*shininessFactor;
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Lighting computation based on a material m,
|
|
// a position on the surface expressed in eye coordinate (typically a vertex
|
|
// position in a vertex shader, something interpolated in a fragment shader),
|
|
// a unit normal to the surface in eye coordinates.
|
|
// The result includes the specular component.
|
|
vec4 singleColor(gl_MaterialParameters m,
|
|
vec3 surfacePosEyeCoords,
|
|
vec3 n)
|
|
{
|
|
vec4 cpri;
|
|
vec4 csec;
|
|
separateSpecularColor(m,surfacePosEyeCoords,n,cpri,csec);
|
|
return cpri+csec;
|
|
}
|
|
|
|
|