581 lines
33 KiB
C++
581 lines
33 KiB
C++
#include <iostream>
|
|
#include <osg/Geode>
|
|
#include <osg/TexGen>
|
|
#include <osg/Material>
|
|
#include <osg/Texture2D>
|
|
#include <osg/MatrixTransform>
|
|
#include <osg/ShapeDrawable>
|
|
#include <osg/BlendFunc>
|
|
#include <osgText/Text>
|
|
#include <osgDB/ReadFile>
|
|
#include <osgViewer/Viewer>
|
|
#include <osgViewer/View>
|
|
#include <osgViewer/CompositeViewer>
|
|
#include <osgGA/TrackballManipulator>
|
|
|
|
#include "VirtualProgram.h"
|
|
|
|
using osgCandidate::VirtualProgram;
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Example shaders assume:
|
|
// one texture
|
|
// one directional light
|
|
// front face lighting
|
|
// color material mode not used (its not supported by GLSL anyway)
|
|
// diffuse/ambient/emissive/specular factors defined in material structure
|
|
// all coords and normal except gl_Position are in view space
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
char MainVertexShaderSource[] =
|
|
"vec4 texture( in vec3 position, in vec3 normal ); \n" //1
|
|
"void lighting( in vec3 position, in vec3 normal ); \n" //2
|
|
" \n" //3
|
|
"void main () \n" //4
|
|
"{ \n" //5
|
|
" gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; \n" //6
|
|
" vec4 position4 = gl_ModelViewMatrix * gl_Vertex; \n" //7
|
|
" vec3 position = position4.xyz / position4.w; \n" //8
|
|
" vec3 normal = normalize( gl_NormalMatrix * gl_Normal ); \n" //9
|
|
" gl_TexCoord[0] = texture( position, normal ); \n" //10
|
|
" lighting( position, normal ); \n" //11
|
|
"} \n";//12
|
|
|
|
char TexCoordTextureVertexShaderSource[] =
|
|
"vec4 texture( in vec3 position, in vec3 normal ) \n" //1
|
|
"{ \n" //2
|
|
" return gl_TextureMatrix[0] * gl_MultiTexCoord0; \n" //3
|
|
"} \n";//4
|
|
|
|
char SphereMapTextureVertexShaderSource[] =
|
|
"vec4 texture( in vec3 position, in vec3 normal ) \n" //1
|
|
"{ \n" //2
|
|
" vec3 u = normalize( position ); \n" //3
|
|
" vec3 r = reflect(u, normal); \n" //4
|
|
" float m = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z+1.0) * (r.z+1.0)); \n" //5
|
|
" return vec4(r.x / m + 0.5, r.y / m + 0.5, 1.0, 1.0 ); \n" //6
|
|
"} \n";//7
|
|
|
|
char PerVertexDirectionalLightingVertexShaderSource[] =
|
|
"void lighting( in vec3 position, in vec3 normal ) \n" //1
|
|
"{ \n" //2
|
|
" float NdotL = dot( normal, normalize(gl_LightSource[0].position.xyz) );\n" //3
|
|
" NdotL = max( 0.0, NdotL ); \n" //4
|
|
" float NdotHV = dot( normal, gl_LightSource[0].halfVector.xyz ); \n" //5
|
|
" NdotHV = max( 0.0, NdotHV ); \n" //6
|
|
" \n" //7
|
|
" gl_FrontColor = gl_FrontLightModelProduct.sceneColor + \n" //8
|
|
" gl_FrontLightProduct[0].ambient + \n" //9
|
|
" gl_FrontLightProduct[0].diffuse * NdotL; \n" //10
|
|
" \n" //11
|
|
" gl_FrontSecondaryColor = vec4(0.0); \n" //12
|
|
" \n" //13
|
|
" if ( NdotL * NdotHV > 0.0 ) \n" //14
|
|
" gl_FrontSecondaryColor = gl_FrontLightProduct[0].specular * \n" //15
|
|
" pow( NdotHV, gl_FrontMaterial.shininess );\n" //16
|
|
" \n" //17
|
|
" gl_BackColor = gl_FrontColor; \n" //18
|
|
" gl_BackSecondaryColor = gl_FrontSecondaryColor; \n" //19
|
|
"} \n";//20
|
|
|
|
char MainFragmentShaderSource[] =
|
|
"vec4 texture( void ); \n" //1
|
|
"void lighting( inout vec4 color ); \n" //2
|
|
" \n" //3
|
|
"void main () \n" //4
|
|
"{ \n" //5
|
|
" vec4 color = texture(); \n" //6
|
|
" lighting( color ); \n" //7
|
|
" gl_FragColor = color; \n" //8
|
|
"} \n";//9
|
|
|
|
char TextureFragmentShaderSource[] =
|
|
"uniform sampler2D baseTexture; \n" //1
|
|
"vec4 texture( void ) \n" //2
|
|
"{ \n" //3
|
|
" return texture2D( baseTexture, gl_TexCoord[0].xy ); \n" //4
|
|
"} \n";//5
|
|
|
|
char ProceduralBlueTextureFragmentShaderSource[] =
|
|
"vec4 texture( void ) \n" //1
|
|
"{ \n" //2
|
|
" return vec4( 0.3, 0.3, 1.0, 1.0 ); \n" //3
|
|
"} \n";//4
|
|
|
|
char PerVertexLightingFragmentShaderSource[] =
|
|
"void lighting( inout vec4 color ) \n" //1
|
|
"{ \n" //2
|
|
" color = color * gl_Color + gl_SecondaryColor; \n" //3
|
|
"} \n";//4
|
|
|
|
char PerFragmentLightingVertexShaderSource[] =
|
|
"varying vec3 Normal; \n" //1
|
|
"varying vec3 Position; \n" //2
|
|
" \n" //3
|
|
"void lighting( in vec3 position, in vec3 normal ) \n" //4
|
|
"{ \n" //5
|
|
" Normal = normal; \n" //6
|
|
" Position = position; \n" //7
|
|
"} \n";//8
|
|
|
|
char PerFragmentDirectionalLightingFragmentShaderSource[] =
|
|
"varying vec3 Normal; \n" //1
|
|
"varying vec3 Position; // not used for directional lighting \n" //2
|
|
" \n" //3
|
|
"void lighting( inout vec4 color ) \n" //4
|
|
"{ \n" //5
|
|
" vec3 n = normalize( Normal ); \n" //5
|
|
" float NdotL = dot( n, normalize(gl_LightSource[0].position.xyz) ); \n" //6
|
|
" NdotL = max( 0.0, NdotL ); \n" //7
|
|
" float NdotHV = dot( n, gl_LightSource[0].halfVector.xyz ); \n" //8
|
|
" NdotHV = max( 0.0, NdotHV ); \n" //9
|
|
" \n" //10
|
|
" color *= gl_FrontLightModelProduct.sceneColor + \n" //11
|
|
" gl_FrontLightProduct[0].ambient + \n" //12
|
|
" gl_FrontLightProduct[0].diffuse * NdotL; \n" //13
|
|
" \n" //14
|
|
" if ( NdotL * NdotHV > 0.0 ) \n" //15
|
|
" color += gl_FrontLightProduct[0].specular * \n" //16
|
|
" pow( NdotHV, gl_FrontMaterial.shininess ); \n" //17
|
|
"} \n";//18
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
osg::Node * CreateModel( const char * file )
|
|
{
|
|
if ( file ) {
|
|
osg::Node * node = NULL;
|
|
node = osgDB::readNodeFile( file );
|
|
if( node )
|
|
return node;
|
|
}
|
|
|
|
// File not found - create textured sphere
|
|
osg::Geode * geode = new osg::Geode;
|
|
osg::ref_ptr<osg::TessellationHints> hints = new osg::TessellationHints;
|
|
hints->setDetailRatio( 0.3 );
|
|
|
|
#if 1
|
|
osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable
|
|
( new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), 4.0 ), hints.get() );
|
|
#else
|
|
osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable
|
|
( new osg::Box( osg::Vec3(-1.0f, -1.0f, -1.0f), 2.0, 2.0, 2.0 ) );
|
|
#endif
|
|
|
|
shape->setColor(osg::Vec4(0.8f, 0.8f, 0.8f, 1.0f));
|
|
|
|
geode->addDrawable( shape.get() );
|
|
|
|
osg::StateSet * stateSet = new osg::StateSet;
|
|
|
|
osg::Texture2D * texture = new osg::Texture2D(
|
|
osgDB::readImageFile("Images/land_shallow_topo_2048.jpg")
|
|
);
|
|
|
|
osg::Material * material = new osg::Material;
|
|
|
|
material->setAmbient
|
|
( osg::Material::FRONT_AND_BACK, osg::Vec4( 0.9, 0.9, 0.9, 1.0 ) );
|
|
|
|
material->setDiffuse
|
|
( osg::Material::FRONT_AND_BACK, osg::Vec4( 0.9, 0.9, 0.9, 1.0 ) );
|
|
|
|
#if 1
|
|
material->setSpecular
|
|
( osg::Material::FRONT_AND_BACK, osg::Vec4( 0.7, 0.3, 0.3, 1.0 ) );
|
|
|
|
material->setShininess( osg::Material::FRONT_AND_BACK, 25 );
|
|
|
|
#endif
|
|
|
|
stateSet->setAttributeAndModes( material );
|
|
stateSet->setTextureAttributeAndModes( 0,texture, osg::StateAttribute::ON );
|
|
|
|
geode->setStateSet( stateSet );
|
|
return geode;
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Convenience method to simplify code a little ...
|
|
void SetVirtualProgramShader( VirtualProgram * virtualProgram,
|
|
std::string shader_semantics,
|
|
osg::Shader::Type shader_type,
|
|
std::string shader_name,
|
|
std::string shader_source )
|
|
{
|
|
osg::Shader * shader = new osg::Shader( shader_type );
|
|
shader->setName( shader_name );
|
|
shader->setShaderSource( shader_source );
|
|
virtualProgram->setShader( shader_semantics, shader );
|
|
}
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
void AddLabel( osg::Group * group, const std::string & label, float offset )
|
|
{
|
|
osg::Vec3 center( 0, 0, offset * 0.5 );
|
|
osg::Geode * geode = new osg::Geode;
|
|
|
|
// Make sure no program breaks text outputs
|
|
geode->getOrCreateStateSet()->setAttribute
|
|
( new osg::Program, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
|
|
|
|
// Turn off stage 1 texture set in parent transform (otherwise it darkens text)
|
|
geode->getOrCreateStateSet()->setTextureMode( 1, GL_TEXTURE_2D, osg::StateAttribute::OFF );
|
|
|
|
group->addChild( geode );
|
|
|
|
osgText::Text* text = new osgText::Text;
|
|
geode->addDrawable( text );
|
|
text->setFont("fonts/times.ttf");
|
|
text->setCharacterSize( offset * 0.1 );
|
|
text->setPosition(center);
|
|
text->setAlignment( osgText::TextBase::CENTER_CENTER );
|
|
text->setAxisAlignment(osgText::Text::SCREEN);
|
|
|
|
osg::Vec4 characterSizeModeColor(1.0f,0.0f,0.5f,1.0f);
|
|
#if 1
|
|
// reproduce outline bounding box compute problem with backdrop on.
|
|
text->setBackdropType(osgText::Text::OUTLINE);
|
|
text->setDrawMode(osgText::Text::TEXT | osgText::Text::BOUNDINGBOX);
|
|
#endif
|
|
|
|
text->setText( label );
|
|
}
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
osg::Node * CreateAdvancedHierarchy( const char * file = NULL )
|
|
{
|
|
osg::Node * model = CreateModel( file );
|
|
if( !model ) return NULL;
|
|
float offset = model->getBound().radius() * 1.3; // diameter
|
|
|
|
// Create transforms for translated instances of the model
|
|
osg::MatrixTransform * transformCenterMiddle = new osg::MatrixTransform( );
|
|
transformCenterMiddle->setMatrix( osg::Matrix::translate( 0,0, offset * 0.5 ) );
|
|
transformCenterMiddle->addChild( model );
|
|
|
|
osg::MatrixTransform * transformCenterTop = new osg::MatrixTransform( );
|
|
transformCenterMiddle->addChild( transformCenterTop );
|
|
transformCenterTop->setMatrix( osg::Matrix::translate( 0,0,offset ) );
|
|
transformCenterTop->addChild( model );
|
|
|
|
osg::MatrixTransform * transformCenterBottom = new osg::MatrixTransform( );
|
|
transformCenterMiddle->addChild( transformCenterBottom );
|
|
transformCenterBottom->setMatrix( osg::Matrix::translate( 0,0,-offset ) );
|
|
transformCenterBottom->addChild( model );
|
|
|
|
osg::MatrixTransform * transformLeftBottom = new osg::MatrixTransform( );
|
|
transformCenterBottom->addChild( transformLeftBottom );
|
|
transformLeftBottom->setMatrix( osg::Matrix::translate( -offset * 0.8,0, -offset * 0.8 ) );
|
|
transformLeftBottom->addChild( model );
|
|
|
|
osg::MatrixTransform * transformRightBottom = new osg::MatrixTransform( );
|
|
transformCenterBottom->addChild( transformRightBottom );
|
|
transformRightBottom->setMatrix( osg::Matrix::translate( offset * 0.8,0, -offset * 0.8 ) );
|
|
transformRightBottom->addChild( model );
|
|
|
|
// Set default VirtualProgram in root StateSet
|
|
// With main vertex and main fragment shaders calling
|
|
// lighting and texture functions defined in aditional shaders
|
|
// Lighting is done per vertex using simple directional light
|
|
// Texture uses stage 0 TexCoords and TexMap
|
|
|
|
if( 1 )
|
|
{
|
|
// NOTE:
|
|
// duplicating the same semantics name in virtual program
|
|
// is only possible if its used for shaders of differing types
|
|
// here for VERTEX and FRAGMENT
|
|
|
|
VirtualProgram * vp = new VirtualProgram( );
|
|
transformCenterMiddle->getOrCreateStateSet()->setAttribute( vp );
|
|
AddLabel( transformCenterMiddle, "Per Vertex Lighting Virtual Program", offset );
|
|
|
|
SetVirtualProgramShader( vp, "main", osg::Shader::VERTEX,
|
|
"Vertex Main", MainVertexShaderSource );
|
|
|
|
SetVirtualProgramShader( vp, "main", osg::Shader::FRAGMENT,
|
|
"Fragment Main", MainFragmentShaderSource );
|
|
|
|
SetVirtualProgramShader( vp, "texture",osg::Shader::VERTEX,
|
|
"Vertex Texture Coord 0", TexCoordTextureVertexShaderSource );
|
|
|
|
SetVirtualProgramShader( vp, "texture",osg::Shader::FRAGMENT,
|
|
"Fragment Texture", TextureFragmentShaderSource );
|
|
|
|
SetVirtualProgramShader( vp, "lighting",osg::Shader::VERTEX,
|
|
"Vertex Lighting", PerVertexDirectionalLightingVertexShaderSource );
|
|
|
|
SetVirtualProgramShader( vp, "lighting",osg::Shader::FRAGMENT,
|
|
"Fragment Lighting", PerVertexLightingFragmentShaderSource );
|
|
|
|
transformCenterMiddle->getOrCreateStateSet()->
|
|
addUniform( new osg::Uniform( "baseTexture", 0 ) );
|
|
|
|
}
|
|
|
|
// Override default vertex ligting with pixel lighting shaders
|
|
// For three bottom models
|
|
if( 1 )
|
|
{
|
|
AddLabel( transformCenterBottom, "Per Pixel Lighting VP", offset );
|
|
VirtualProgram * vp = new VirtualProgram( );
|
|
transformCenterBottom->getOrCreateStateSet()->setAttribute( vp );
|
|
|
|
SetVirtualProgramShader( vp, "lighting",osg::Shader::VERTEX,
|
|
"Vertex Shader For Per Pixel Lighting",
|
|
PerFragmentLightingVertexShaderSource );
|
|
|
|
SetVirtualProgramShader( vp, "lighting",osg::Shader::FRAGMENT,
|
|
"Fragment Shader For Per Pixel Lighting",
|
|
PerFragmentDirectionalLightingFragmentShaderSource );
|
|
}
|
|
|
|
// Additionaly set bottom left model texture to procedural blue to
|
|
// better observe smooth speculars done through per pixel lighting
|
|
if( 1 )
|
|
{
|
|
AddLabel( transformLeftBottom, "Blue Tex VP", offset );
|
|
VirtualProgram * vp = new VirtualProgram( );
|
|
transformLeftBottom->getOrCreateStateSet()->setAttribute( vp );
|
|
|
|
SetVirtualProgramShader( vp, "texture",osg::Shader::FRAGMENT,
|
|
"Fragment Shader Procedural Blue Tex",
|
|
ProceduralBlueTextureFragmentShaderSource );
|
|
}
|
|
|
|
// Additionaly change texture mapping to SphereMAp in bottom right model
|
|
if( 1 )
|
|
{
|
|
AddLabel( transformRightBottom, "EnvMap Sphere VP", offset );
|
|
|
|
osg::StateSet * ss = transformRightBottom->getOrCreateStateSet();
|
|
VirtualProgram * vp = new VirtualProgram( );
|
|
ss->setAttribute( vp );
|
|
SetVirtualProgramShader( vp, "texture",osg::Shader::VERTEX,
|
|
"Vertex Texture Sphere Map", SphereMapTextureVertexShaderSource );
|
|
|
|
osg::Texture2D * texture = new osg::Texture2D(
|
|
// osgDB::readImageFile("Images/reflect.rgb")
|
|
osgDB::readImageFile("Images/skymap.jpg")
|
|
);
|
|
|
|
// Texture is set on stage 1 to not interfere with label text
|
|
// The same could be achieved with texture override
|
|
// but such approach also turns off label texture
|
|
ss->setTextureAttributeAndModes( 1, texture, osg::StateAttribute::ON );
|
|
ss->addUniform( new osg::Uniform( "baseTexture", 1 ) );
|
|
|
|
#if 0 // Could be useful with Fixed Vertex Pipeline
|
|
osg::TexGen * texGen = new osg::TexGen();
|
|
texGen->setMode( osg::TexGen::SPHERE_MAP );
|
|
|
|
// Texture states applied
|
|
ss->setTextureAttributeAndModes( 1, texGen, osg::StateAttribute::ON );
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
// Top center model usues osg::Program overriding VirtualProgram in model
|
|
if( 1 )
|
|
{
|
|
AddLabel( transformCenterTop, "Fixed Vertex + Simple Fragment osg::Program", offset );
|
|
osg::Program * program = new osg::Program;
|
|
program->setName( "Trivial Fragment + Fixed Vertex Program" );
|
|
|
|
transformCenterTop->getOrCreateStateSet( )->setAttributeAndModes
|
|
( program, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
|
|
|
|
osg::Shader * shader = new osg::Shader( osg::Shader::FRAGMENT );
|
|
shader->setName( "Trivial Fragment Shader" );
|
|
shader->setShaderSource(
|
|
"uniform sampler2D baseTexture; \n"
|
|
"void main(void) \n"
|
|
"{ \n"
|
|
" gl_FragColor = gl_Color * texture2D( baseTexture,gl_TexCoord[0].xy);\n"
|
|
"} \n"
|
|
);
|
|
|
|
program->addShader( shader );
|
|
}
|
|
|
|
return transformCenterMiddle;
|
|
}
|
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
// Shders not used in the example but left for fun if anyone wants to play
|
|
char LightingVertexShaderSource[] =
|
|
"// Forward declarations \n" //1
|
|
" \n" //2
|
|
"void SpotLight( in int i, in vec3 eye, in vec3 position, in vec3 normal, \n" //3
|
|
" inout vec4 ambient, inout vec4 diffuse, inout vec4 specular ); \n" //4
|
|
" \n" //5
|
|
"void PointLight( in int i, in vec3 eye, in vec3 position, in vec3 normal, \n" //6
|
|
" inout vec4 ambient, inout vec4 diffuse, inout vec4 specular ); \n" //7
|
|
" \n" //8
|
|
"void DirectionalLight( in int i, in vec3 normal, \n" //9
|
|
" inout vec4 ambient, inout vec4 diffuse, inout vec4 specular ); \n" //10
|
|
" \n" //11
|
|
"const int NumEnabledLights = 1; \n" //12
|
|
" \n" //13
|
|
"void lighting( in vec3 position, in vec3 normal ) \n" //14
|
|
"{ \n" //15
|
|
" vec3 eye = vec3( 0.0, 0.0, 1.0 ); \n" //16
|
|
" //vec3 eye = -normalize(position); \n" //17
|
|
" \n" //18
|
|
" // Clear the light intensity accumulators \n" //19
|
|
" vec4 amb = vec4(0.0); \n" //20
|
|
" vec4 diff = vec4(0.0); \n" //21
|
|
" vec4 spec = vec4(0.0); \n" //22
|
|
" \n" //23
|
|
" // Loop through enabled lights, compute contribution from each \n" //24
|
|
" for (int i = 0; i < NumEnabledLights; i++) \n" //25
|
|
" { \n" //26
|
|
" if (gl_LightSource[i].position.w == 0.0) \n" //27
|
|
" DirectionalLight(i, normal, amb, diff, spec); \n" //28
|
|
" else if (gl_LightSource[i].spotCutoff == 180.0) \n" //29
|
|
" PointLight(i, eye, position, normal, amb, diff, spec); \n" //30
|
|
" else \n" //31
|
|
" SpotLight(i, eye, position, normal, amb, diff, spec); \n" //32
|
|
" } \n" //33
|
|
" \n" //34
|
|
" gl_FrontColor = gl_FrontLightModelProduct.sceneColor + \n" //35
|
|
" amb * gl_FrontMaterial.ambient + \n" //36
|
|
" diff * gl_FrontMaterial.diffuse; \n" //37
|
|
" \n" //38
|
|
" gl_FrontSecondaryColor = vec4(spec*gl_FrontMaterial.specular); \n" //39
|
|
" \n" //40
|
|
" gl_BackColor = gl_FrontColor; \n" //41
|
|
" gl_BackSecondaryColor = gl_FrontSecondaryColor; \n" //42
|
|
"} \n";//43
|
|
|
|
char SpotLightShaderSource[] =
|
|
"void SpotLight(in int i, \n" //1
|
|
" in vec3 eye, \n" //2
|
|
" in vec3 position, \n" //3
|
|
" in vec3 normal, \n" //4
|
|
" inout vec4 ambient, \n" //5
|
|
" inout vec4 diffuse, \n" //6
|
|
" inout vec4 specular) \n" //7
|
|
"{ \n" //8
|
|
" float nDotVP; // normal . light direction \n" //9
|
|
" float nDotHV; // normal . light half vector \n" //10
|
|
" float pf; // power factor \n" //11
|
|
" float spotDot; // cosine of angle between spotlight \n" //12
|
|
" float spotAttenuation; // spotlight attenuation factor \n" //13
|
|
" float attenuation; // computed attenuation factor \n" //14
|
|
" float d; // distance from surface to light source \n" //15
|
|
" vec3 VP; // direction from surface to light position \n" //16
|
|
" vec3 halfVector; // direction of maximum highlights \n" //17
|
|
" \n" //18
|
|
" // Compute vector from surface to light position \n" //19
|
|
" VP = vec3(gl_LightSource[i].position) - position; \n" //20
|
|
" \n" //21
|
|
" // Compute distance between surface and light position \n" //22
|
|
" d = length(VP); \n" //23
|
|
" \n" //24
|
|
" // Normalize the vector from surface to light position \n" //25
|
|
" VP = normalize(VP); \n" //26
|
|
" \n" //27
|
|
" // Compute attenuation \n" //28
|
|
" attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + \n" //29
|
|
" gl_LightSource[i].linearAttenuation * d + \n" //30
|
|
" gl_LightSource[i].quadraticAttenuation *d*d); \n" //31
|
|
" \n" //32
|
|
" // See if point on surface is inside cone of illumination \n" //33
|
|
" spotDot = dot(-VP, normalize(gl_LightSource[i].spotDirection)); \n" //34
|
|
" \n" //35
|
|
" if (spotDot < gl_LightSource[i].spotCosCutoff) \n" //36
|
|
" spotAttenuation = 0.0; // light adds no contribution \n" //37
|
|
" else \n" //38
|
|
" spotAttenuation = pow(spotDot, gl_LightSource[i].spotExponent); \n" //39
|
|
" \n" //40
|
|
" // Combine the spotlight and distance attenuation. \n" //41
|
|
" attenuation *= spotAttenuation; \n" //42
|
|
" \n" //43
|
|
" halfVector = normalize(VP + eye); \n" //44
|
|
" \n" //45
|
|
" nDotVP = max(0.0, dot(normal, VP)); \n" //46
|
|
" nDotHV = max(0.0, dot(normal, halfVector)); \n" //47
|
|
" \n" //48
|
|
" if (nDotVP == 0.0) \n" //49
|
|
" pf = 0.0; \n" //50
|
|
" else \n" //51
|
|
" pf = pow(nDotHV, gl_FrontMaterial.shininess); \n" //52
|
|
" \n" //53
|
|
" ambient += gl_LightSource[i].ambient * attenuation; \n" //54
|
|
" diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation; \n" //55
|
|
" specular += gl_LightSource[i].specular * pf * attenuation; \n" //56
|
|
"} \n";//57
|
|
|
|
char PointLightShaderSource[] =
|
|
"void PointLight(in int i, \n" //1
|
|
" in vec3 eye, \n" //2
|
|
" in vec3 position, \n" //3
|
|
" in vec3 normal, \n" //4
|
|
" inout vec4 ambient, \n" //5
|
|
" inout vec4 diffuse, \n" //6
|
|
" inout vec4 specular) \n" //7
|
|
"{ \n" //8
|
|
" float nDotVP; // normal . light direction \n" //9
|
|
" float nDotHV; // normal . light half vector \n" //10
|
|
" float pf; // power factor \n" //11
|
|
" float attenuation; // computed attenuation factor \n" //12
|
|
" float d; // distance from surface to light source \n" //13
|
|
" vec3 VP; // direction from surface to light position \n" //14
|
|
" vec3 halfVector; // direction of maximum highlights \n" //15
|
|
" \n" //16
|
|
" // Compute vector from surface to light position \n" //17
|
|
" VP = vec3(gl_LightSource[i].position) - position; \n" //18
|
|
" \n" //19
|
|
" // Compute distance between surface and light position \n" //20
|
|
" d = length(VP); \n" //21
|
|
" \n" //22
|
|
" // Normalize the vector from surface to light position \n" //23
|
|
" VP = normalize(VP); \n" //24
|
|
" \n" //25
|
|
" // Compute attenuation \n" //26
|
|
" attenuation = 1.0 / (gl_LightSource[i].constantAttenuation + \n" //27
|
|
" gl_LightSource[i].linearAttenuation * d + \n" //28
|
|
" gl_LightSource[i].quadraticAttenuation * d*d); \n" //29
|
|
" \n" //30
|
|
" halfVector = normalize(VP + eye); \n" //31
|
|
" \n" //32
|
|
" nDotVP = max(0.0, dot(normal, VP)); \n" //33
|
|
" nDotHV = max(0.0, dot(normal, halfVector)); \n" //34
|
|
" \n" //35
|
|
" if (nDotVP == 0.0) \n" //36
|
|
" pf = 0.0; \n" //37
|
|
" else \n" //38
|
|
" pf = pow(nDotHV, gl_FrontMaterial.shininess); \n" //39
|
|
" \n" //40
|
|
" ambient += gl_LightSource[i].ambient * attenuation; \n" //41
|
|
" diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation; \n" //42
|
|
" specular += gl_LightSource[i].specular * pf * attenuation; \n" //43
|
|
"} \n";//44
|
|
|
|
char DirectionalLightShaderSource[] =
|
|
"void DirectionalLight(in int i, \n" //1
|
|
" in vec3 normal, \n" //2
|
|
" inout vec4 ambient, \n" //3
|
|
" inout vec4 diffuse, \n" //4
|
|
" inout vec4 specular) \n" //5
|
|
"{ \n" //6
|
|
" float nDotVP; // normal . light direction \n" //7
|
|
" float nDotHV; // normal . light half vector \n" //8
|
|
" float pf; // power factor \n" //9
|
|
" \n" //10
|
|
" nDotVP = max(0.0, dot(normal, \n" //11
|
|
" normalize(vec3(gl_LightSource[i].position)))); \n" //12
|
|
" nDotHV = max(0.0, dot(normal, \n" //13
|
|
" vec3(gl_LightSource[i].halfVector))); \n" //14
|
|
" \n" //15
|
|
" if (nDotVP == 0.0) \n" //16
|
|
" pf = 0.0; \n" //17
|
|
" else \n" //18
|
|
" pf = pow(nDotHV, gl_FrontMaterial.shininess); \n" //19
|
|
" \n" //20
|
|
" ambient += gl_LightSource[i].ambient; \n" //21
|
|
" diffuse += gl_LightSource[i].diffuse * nDotVP; \n" //22
|
|
" specular += gl_LightSource[i].specular * pf; \n" //23
|
|
"} \n";//24
|
|
|