1 #include <iostream>
2 #include <osg/Geode>
3 #include <osg/TexGen>
4 #include <osg/Texture2D>
5 #include <osg/MatrixTransform>
6 #include <osg/BlendFunc>
7 #include <osgText/Text>
8 #include <osgDB/ReadFile>
9 
10 #include "VirtualProgram.h"
11 
12 using osgCandidate::VirtualProgram;
13 
14 ////////////////////////////////////////////////////////////////////////////////
15 // Example shaders assume:
16 // one texture
17 // one directional light
18 // front face lighting
19 // color material mode not used (its not supported by GLSL anyway)
20 // diffuse/ambient/emissive/specular factors defined in material structure
21 // all coords and normal except gl_Position are in view space
22 ////////////////////////////////////////////////////////////////////////////////
23 
24 char MainVertexShaderSource[] =
25 "vec4 texture( in vec3 position, in vec3 normal );                          \n" //1
26 "void lighting( in vec3 position, in vec3 normal );                         \n" //2
27 "                                                                           \n" //3
28 "void main ()                                                               \n" //4
29 "{                                                                          \n" //5
30 "    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;                \n" //6
31 "    vec4 position4 = gl_ModelViewMatrix * gl_Vertex;                       \n" //7
32 "    vec3 position = position4.xyz / position4.w;                           \n" //8
33 "    vec3 normal = normalize( gl_NormalMatrix * gl_Normal );                \n" //9
34 "    gl_TexCoord[0] = texture( position, normal );                          \n" //10
35 "    lighting( position, normal );                                          \n" //11
36 "}                                                                          \n";//12
37 
38 char TexCoordTextureVertexShaderSource[] =
39 "vec4 texture( in vec3 position, in vec3 normal )                           \n" //1
40 "{                                                                          \n" //2
41 "    return gl_TextureMatrix[0] * gl_MultiTexCoord0;                        \n" //3
42 "}                                                                          \n";//4
43 
44 char SphereMapTextureVertexShaderSource[] =
45 "vec4 texture( in vec3 position, in vec3 normal )                           \n" //1
46 "{                                                                          \n" //2
47 "    vec3 u = normalize( position );                                        \n" //3
48 "    vec3 r = reflect(u, normal);                                           \n" //4
49 "    float m = 2.0 * sqrt(r.x * r.x + r.y * r.y + (r.z+1.0) * (r.z+1.0));   \n" //5
50 "    return vec4(r.x / m + 0.5, r.y / m + 0.5, 1.0, 1.0 );                  \n" //6
51 "}                                                                          \n";//7
52 
53 char PerVertexDirectionalLightingVertexShaderSource[] =
54 "void lighting( in vec3 position, in vec3 normal )                          \n" //1
55 "{                                                                          \n" //2
56 "    float NdotL = dot( normal, normalize(gl_LightSource[0].position.xyz) );\n" //3
57 "    NdotL = max( 0.0, NdotL );                                             \n" //4
58 "    float NdotHV = dot( normal, gl_LightSource[0].halfVector.xyz );        \n" //5
59 "    NdotHV = max( 0.0, NdotHV );                                           \n" //6
60 "                                                                           \n" //7
61 "    gl_FrontColor = gl_FrontLightModelProduct.sceneColor +                 \n" //8
62 "                    gl_FrontLightProduct[0].ambient +                      \n" //9
63 "                    gl_FrontLightProduct[0].diffuse * NdotL;               \n" //10
64 "                                                                           \n" //11
65 "    gl_FrontSecondaryColor = vec4(0.0);                                    \n" //12
66 "                                                                           \n" //13
67 "    if ( NdotL * NdotHV > 0.0 )                                            \n" //14
68 "        gl_FrontSecondaryColor = gl_FrontLightProduct[0].specular *        \n" //15
69 "                                 pow( NdotHV, gl_FrontMaterial.shininess );\n" //16
70 "                                                                           \n" //17
71 "    gl_BackColor = gl_FrontColor;                                          \n" //18
72 "    gl_BackSecondaryColor = gl_FrontSecondaryColor;                        \n" //19
73 "}                                                                          \n";//20
74 
75 char MainFragmentShaderSource[] =
76 "vec4 texture( void );                                                      \n" //1
77 "void lighting( inout vec4 color );                                         \n" //2
78 "                                                                           \n" //3
79 "void main ()                                                               \n" //4
80 "{                                                                          \n" //5
81 "    vec4 color = texture();                                                \n" //6
82 "    lighting( color );                                                     \n" //7
83 "    gl_FragColor = color;                                                  \n" //8
84 "}                                                                          \n";//9
85 
86 char TextureFragmentShaderSource[] =
87 "uniform sampler2D baseTexture;                                             \n" //1
88 "vec4 texture( void )                                                       \n" //2
89 "{                                                                          \n" //3
90 "    return texture2D( baseTexture, gl_TexCoord[0].xy );                    \n" //4
91 "}                                                                          \n";//5
92 
93 char ProceduralBlueTextureFragmentShaderSource[] =
94 "vec4 texture( void )                                                       \n" //1
95 "{                                                                          \n" //2
96 "    return vec4( 0.3, 0.3, 1.0, 1.0 );                                     \n" //3
97 "}                                                                          \n";//4
98 
99 char PerVertexLightingFragmentShaderSource[] =
100 "void lighting( inout vec4 color )                                          \n" //1
101 "{                                                                          \n" //2
102 "    color = color * gl_Color + gl_SecondaryColor;                          \n" //3
103 "}                                                                          \n";//4
104 
105 char PerFragmentLightingVertexShaderSource[] =
106 "varying vec3 Normal;                                                       \n" //1
107 "varying vec3 Position;                                                     \n" //2
108 "                                                                           \n" //3
109 "void lighting( in vec3 position, in vec3 normal )                          \n" //4
110 "{                                                                          \n" //5
111 "    Normal = normal;                                                       \n" //6
112 "    Position = position;                                                   \n" //7
113 "}                                                                          \n";//8
114 
115 char PerFragmentDirectionalLightingFragmentShaderSource[] =
116 "varying vec3 Normal;                                                       \n" //1
117 "varying vec3 Position; // not used for directional lighting                \n" //2
118 "                                                                           \n" //3
119 "void lighting( inout vec4 color )                                          \n" //4
120 "{                                                                          \n" //5
121 "    vec3 n = normalize( Normal );                                          \n" //5
122 "    float NdotL = dot( n, normalize(gl_LightSource[0].position.xyz) );     \n" //6
123 "    NdotL = max( 0.0, NdotL );                                             \n" //7
124 "    float NdotHV = dot( n, gl_LightSource[0].halfVector.xyz );             \n" //8
125 "    NdotHV = max( 0.0, NdotHV );                                           \n" //9
126 "                                                                           \n" //10
127 "    color *= gl_FrontLightModelProduct.sceneColor +                        \n" //11
128 "             gl_FrontLightProduct[0].ambient +                             \n" //12
129 "             gl_FrontLightProduct[0].diffuse * NdotL;                      \n" //13
130 "                                                                           \n" //14
131 "    if ( NdotL * NdotHV > 0.0 )                                            \n" //15
132 "        color += gl_FrontLightProduct[0].specular *                        \n" //16
133 "                 pow( NdotHV, gl_FrontMaterial.shininess );                \n" //17
134 "}                                                                          \n";//18
135 
136 ////////////////////////////////////////////////////////////////////////////////
137 // Convenience method to simplify code a little ...
SetVirtualProgramShader(VirtualProgram * virtualProgram,std::string shader_semantics,osg::Shader::Type shader_type,std::string shader_name,std::string shader_source)138 void SetVirtualProgramShader( VirtualProgram * virtualProgram,
139                               std::string shader_semantics,
140                               osg::Shader::Type shader_type,
141                               std::string shader_name,
142                               std::string shader_source )
143 {
144     osg::Shader * shader = new osg::Shader( shader_type );
145     shader->setName( shader_name );
146     shader->setShaderSource( shader_source );
147     virtualProgram->setShader( shader_semantics, shader );
148 }
149 ///////////////////////////////////////////////////////////////////////////////
AddLabel(osg::Group * group,const std::string & label,float offset)150 void AddLabel( osg::Group * group, const std::string & label, float offset )
151 {
152     osg::Vec3 center( 0, 0, offset * 0.5 );
153     osg::Geode * geode = new osg::Geode;
154 
155     // Make sure no program breaks text outputs
156     geode->getOrCreateStateSet()->setAttribute
157       ( new osg::Program, osg::StateAttribute::ON | osg::StateAttribute::PROTECTED );
158 
159     // Turn off stage 1 texture set in parent transform (otherwise it darkens text)
160     geode->getOrCreateStateSet()->setTextureMode( 1, GL_TEXTURE_2D, osg::StateAttribute::OFF );
161 
162     group->addChild( geode );
163 
164     osgText::Text* text = new osgText::Text;
165     geode->addDrawable( text );
166     text->setFont("fonts/times.ttf");
167     text->setCharacterSize( offset * 0.1 );
168     text->setPosition(center);
169     text->setAlignment( osgText::TextBase::CENTER_CENTER );
170     text->setAxisAlignment(osgText::Text::SCREEN);
171 
172     osg::Vec4 characterSizeModeColor(1.0f,0.0f,0.5f,1.0f);
173 #if 1
174     // reproduce outline bounding box compute problem with backdrop on.
175     text->setBackdropType(osgText::Text::OUTLINE);
176     text->setDrawMode(osgText::Text::TEXT | osgText::Text::BOUNDINGBOX);
177 #endif
178 
179     text->setText( label );
180 }
181 ////////////////////////////////////////////////////////////////////////////////
CreateAdvancedHierarchy(osg::Node * model)182 osg::Node * CreateAdvancedHierarchy( osg::Node * model )
183 {
184     if( !model ) return NULL;
185     float offset = model->getBound().radius() * 1.3; // diameter
186 
187     // Create transforms for translated instances of the model
188     osg::MatrixTransform * transformCenterMiddle  = new osg::MatrixTransform( );
189     transformCenterMiddle->setMatrix( osg::Matrix::translate( 0,0, offset * 0.5 ) );
190     transformCenterMiddle->addChild( model );
191 
192     osg::MatrixTransform * transformCenterTop  = new osg::MatrixTransform( );
193     transformCenterMiddle->addChild( transformCenterTop );
194     transformCenterTop->setMatrix( osg::Matrix::translate( 0,0,offset ) );
195     transformCenterTop->addChild( model );
196 
197     osg::MatrixTransform * transformCenterBottom  = new osg::MatrixTransform( );
198     transformCenterMiddle->addChild( transformCenterBottom );
199     transformCenterBottom->setMatrix( osg::Matrix::translate( 0,0,-offset ) );
200     transformCenterBottom->addChild( model );
201 
202     osg::MatrixTransform * transformLeftBottom  = new osg::MatrixTransform( );
203     transformCenterBottom->addChild( transformLeftBottom );
204     transformLeftBottom->setMatrix( osg::Matrix::translate( -offset * 0.8,0, -offset * 0.8 ) );
205     transformLeftBottom->addChild( model );
206 
207     osg::MatrixTransform * transformRightBottom  = new osg::MatrixTransform( );
208     transformCenterBottom->addChild( transformRightBottom );
209     transformRightBottom->setMatrix( osg::Matrix::translate( offset * 0.8,0, -offset * 0.8 ) );
210     transformRightBottom->addChild( model );
211 
212     // Set default VirtualProgram in root StateSet
213     // With main vertex and main fragment shaders calling
214     // lighting and texture functions defined in additional shaders
215     // Lighting is done per vertex using simple directional light
216     // Texture uses stage 0 TexCoords and TexMap
217 
218     if( 1 )
219     {
220         // NOTE:
221         // duplicating the same semantics name in virtual program
222         // is only possible if its used for shaders of differing types
223         // here for VERTEX and FRAGMENT
224 
225         VirtualProgram * vp = new VirtualProgram( );
226         transformCenterMiddle->getOrCreateStateSet()->setAttribute( vp );
227         AddLabel( transformCenterMiddle, "Per Vertex Lighting Virtual Program", offset );
228 
229         SetVirtualProgramShader( vp, "main", osg::Shader::VERTEX,
230             "Vertex Main", MainVertexShaderSource );
231 
232         SetVirtualProgramShader( vp, "main", osg::Shader::FRAGMENT,
233             "Fragment Main", MainFragmentShaderSource );
234 
235         SetVirtualProgramShader( vp, "texture",osg::Shader::VERTEX,
236             "Vertex Texture Coord 0", TexCoordTextureVertexShaderSource );
237 
238         SetVirtualProgramShader( vp, "texture",osg::Shader::FRAGMENT,
239             "Fragment Texture", TextureFragmentShaderSource );
240 
241         SetVirtualProgramShader( vp, "lighting",osg::Shader::VERTEX,
242             "Vertex Lighting", PerVertexDirectionalLightingVertexShaderSource );
243 
244         SetVirtualProgramShader( vp, "lighting",osg::Shader::FRAGMENT,
245             "Fragment Lighting", PerVertexLightingFragmentShaderSource );
246 
247         transformCenterMiddle->getOrCreateStateSet()->
248             addUniform( new osg::Uniform( "baseTexture", 0 ) );
249 
250     }
251 
252     // Override default vertex ligting with pixel lighting shaders
253     // For three bottom models
254     if( 1 )
255     {
256         AddLabel( transformCenterBottom, "Per Pixel Lighting VP", offset );
257         VirtualProgram * vp = new VirtualProgram( );
258         transformCenterBottom->getOrCreateStateSet()->setAttribute( vp );
259 
260         SetVirtualProgramShader( vp, "lighting",osg::Shader::VERTEX,
261             "Vertex Shader For Per Pixel Lighting",
262             PerFragmentLightingVertexShaderSource );
263 
264         SetVirtualProgramShader( vp, "lighting",osg::Shader::FRAGMENT,
265             "Fragment Shader For Per Pixel Lighting",
266             PerFragmentDirectionalLightingFragmentShaderSource );
267     }
268 
269     // Additionally set bottom left model texture to procedural blue to
270     // better observe smooth speculars done through per pixel lighting
271     if( 1 )
272     {
273         AddLabel( transformLeftBottom, "Blue Tex VP", offset );
274         VirtualProgram * vp = new VirtualProgram( );
275         transformLeftBottom->getOrCreateStateSet()->setAttribute( vp );
276 
277         SetVirtualProgramShader( vp, "texture",osg::Shader::FRAGMENT,
278             "Fragment Shader Procedural Blue Tex",
279             ProceduralBlueTextureFragmentShaderSource );
280     }
281 
282     // Additionally change texture mapping to SphereMAp in bottom right model
283     if( 1 )
284     {
285         AddLabel( transformRightBottom, "EnvMap Sphere VP", offset );
286 
287         osg::StateSet * ss = transformRightBottom->getOrCreateStateSet();
288         VirtualProgram * vp = new VirtualProgram( );
289         ss->setAttribute( vp );
290         SetVirtualProgramShader( vp, "texture",osg::Shader::VERTEX,
291             "Vertex Texture Sphere Map", SphereMapTextureVertexShaderSource );
292 
293         osg::Texture2D * texture =  new osg::Texture2D( osgDB::readRefImageFile("Images/skymap.jpg") );
294 
295         // Texture is set on stage 1 to not interfere with label text
296         // The same could be achieved with texture override
297         // but such approach also turns off label texture
298         ss->setTextureAttributeAndModes( 1, texture, osg::StateAttribute::ON );
299         ss->addUniform( new osg::Uniform( "baseTexture", 1 ) );
300 
301 #if 0 // Could be useful with Fixed Vertex Pipeline
302         osg::TexGen * texGen = new osg::TexGen();
303         texGen->setMode( osg::TexGen::SPHERE_MAP );
304 
305         // Texture states applied
306         ss->setTextureAttributeAndModes( 1, texGen, osg::StateAttribute::ON );
307 #endif
308 
309     }
310 
311 
312     // Top center model usues osg::Program overriding VirtualProgram in model
313     if( 1 )
314     {
315         AddLabel( transformCenterTop, "Fixed Vertex + Simple Fragment osg::Program", offset );
316         osg::Program * program = new osg::Program;
317         program->setName( "Trivial Fragment + Fixed Vertex Program" );
318 
319         transformCenterTop->getOrCreateStateSet( )->setAttributeAndModes
320             ( program, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
321 
322         osg::Shader * shader = new osg::Shader( osg::Shader::FRAGMENT );
323         shader->setName( "Trivial Fragment Shader" );
324         shader->setShaderSource(
325             "uniform sampler2D baseTexture;                                          \n"
326             "void main(void)                                                         \n"
327             "{                                                                       \n"
328             "    gl_FragColor = gl_Color * texture2D( baseTexture,gl_TexCoord[0].xy);\n"
329             "}                                                                       \n"
330             );
331 
332         program->addShader( shader );
333     }
334 
335     return transformCenterMiddle;
336 }
337 
338 ////////////////////////////////////////////////////////////////////////////////
339 // Shders not used in the example but left for fun if anyone wants to play
340 char LightingVertexShaderSource[] =
341 "// Forward declarations                                                    \n" //1
342 "                                                                           \n" //2
343 "void SpotLight( in int i, in vec3 eye, in vec3 position, in vec3 normal,   \n" //3
344 "            inout vec4 ambient, inout vec4 diffuse, inout vec4 specular ); \n" //4
345 "                                                                           \n" //5
346 "void PointLight( in int i, in vec3 eye, in vec3 position, in vec3 normal,  \n" //6
347 "            inout vec4 ambient, inout vec4 diffuse, inout vec4 specular ); \n" //7
348 "                                                                           \n" //8
349 "void DirectionalLight( in int i, in vec3 normal,                           \n" //9
350 "            inout vec4 ambient, inout vec4 diffuse, inout vec4 specular ); \n" //10
351 "                                                                           \n" //11
352 "const int NumEnabledLights = 1;                                            \n" //12
353 "                                                                           \n" //13
354 "void lighting( in vec3 position, in vec3 normal )                          \n" //14
355 "{                                                                          \n" //15
356 "    vec3  eye = vec3( 0.0, 0.0, 1.0 );                                     \n" //16
357 "    //vec3  eye = -normalize(position);                                    \n" //17
358 "                                                                           \n" //18
359 "    // Clear the light intensity accumulators                              \n" //19
360 "    vec4 amb  = vec4(0.0);                                                 \n" //20
361 "    vec4 diff = vec4(0.0);                                                 \n" //21
362 "    vec4 spec = vec4(0.0);                                                 \n" //22
363 "                                                                           \n" //23
364 "    // Loop through enabled lights, compute contribution from each         \n" //24
365 "    for (int i = 0; i < NumEnabledLights; i++)                             \n" //25
366 "   {                                                                       \n" //26
367 "       if (gl_LightSource[i].position.w == 0.0)                            \n" //27
368 "           DirectionalLight(i, normal, amb, diff, spec);                   \n" //28
369 "       else if (gl_LightSource[i].spotCutoff == 180.0)                     \n" //29
370 "           PointLight(i, eye, position, normal, amb, diff, spec);          \n" //30
371 "       else                                                                \n" //31
372 "           SpotLight(i, eye, position, normal, amb, diff, spec);           \n" //32
373 "    }                                                                      \n" //33
374 "                                                                           \n" //34
375 "    gl_FrontColor = gl_FrontLightModelProduct.sceneColor +                 \n" //35
376 "                    amb * gl_FrontMaterial.ambient +                       \n" //36
377 "                    diff * gl_FrontMaterial.diffuse;                       \n" //37
378 "                                                                           \n" //38
379 "    gl_FrontSecondaryColor = vec4(spec*gl_FrontMaterial.specular);         \n" //39
380 "                                                                           \n" //40
381 "    gl_BackColor = gl_FrontColor;                                          \n" //41
382 "    gl_BackSecondaryColor = gl_FrontSecondaryColor;                        \n" //42
383 "}                                                                          \n";//43
384 
385 char SpotLightShaderSource[] =
386 "void SpotLight(in int i,                                                   \n" //1
387 "               in vec3 eye,                                                \n" //2
388 "               in vec3 position,                                           \n" //3
389 "               in vec3 normal,                                             \n" //4
390 "               inout vec4 ambient,                                         \n" //5
391 "               inout vec4 diffuse,                                         \n" //6
392 "               inout vec4 specular)                                        \n" //7
393 "{                                                                          \n" //8
394 "    float nDotVP;          // normal . light direction                     \n" //9
395 "    float nDotHV;          // normal . light half vector                   \n" //10
396 "    float pf;              // power factor                                 \n" //11
397 "    float spotDot;         // cosine of angle between spotlight            \n" //12
398 "    float spotAttenuation; // spotlight attenuation factor                 \n" //13
399 "    float attenuation;     // computed attenuation factor                  \n" //14
400 "    float d;               // distance from surface to light source        \n" //15
401 "    vec3 VP;               // direction from surface to light position     \n" //16
402 "    vec3 halfVector;       // direction of maximum highlights              \n" //17
403 "                                                                           \n" //18
404 "    // Compute vector from surface to light position                       \n" //19
405 "    VP = vec3(gl_LightSource[i].position) - position;                      \n" //20
406 "                                                                           \n" //21
407 "    // Compute distance between surface and light position                 \n" //22
408 "    d = length(VP);                                                        \n" //23
409 "                                                                           \n" //24
410 "    // Normalize the vector from surface to light position                 \n" //25
411 "    VP = normalize(VP);                                                    \n" //26
412 "                                                                           \n" //27
413 "    // Compute attenuation                                                 \n" //28
414 "    attenuation = 1.0 / (gl_LightSource[i].constantAttenuation +           \n" //29
415 "                         gl_LightSource[i].linearAttenuation * d +         \n" //30
416 "                         gl_LightSource[i].quadraticAttenuation *d*d);     \n" //31
417 "                                                                           \n" //32
418 "    // See if point on surface is inside cone of illumination              \n" //33
419 "    spotDot = dot(-VP, normalize(gl_LightSource[i].spotDirection));        \n" //34
420 "                                                                           \n" //35
421 "    if (spotDot < gl_LightSource[i].spotCosCutoff)                         \n" //36
422 "        spotAttenuation = 0.0; // light adds no contribution               \n" //37
423 "    else                                                                   \n" //38
424 "        spotAttenuation = pow(spotDot, gl_LightSource[i].spotExponent);    \n" //39
425 "                                                                           \n" //40
426 "    // Combine the spotlight and distance attenuation.                     \n" //41
427 "    attenuation *= spotAttenuation;                                        \n" //42
428 "                                                                           \n" //43
429 "    halfVector = normalize(VP + eye);                                      \n" //44
430 "                                                                           \n" //45
431 "    nDotVP = max(0.0, dot(normal, VP));                                    \n" //46
432 "    nDotHV = max(0.0, dot(normal, halfVector));                            \n" //47
433 "                                                                           \n" //48
434 "    if (nDotVP == 0.0)                                                     \n" //49
435 "        pf = 0.0;                                                          \n" //50
436 "    else                                                                   \n" //51
437 "        pf = pow(nDotHV, gl_FrontMaterial.shininess);                      \n" //52
438 "                                                                           \n" //53
439 "    ambient  += gl_LightSource[i].ambient * attenuation;                   \n" //54
440 "    diffuse  += gl_LightSource[i].diffuse * nDotVP * attenuation;          \n" //55
441 "    specular += gl_LightSource[i].specular * pf * attenuation;             \n" //56
442 "}                                                                          \n";//57
443 
444 char PointLightShaderSource[] =
445 "void PointLight(in int i,                                                  \n" //1
446 "                in vec3 eye,                                               \n" //2
447 "                in vec3 position,                                          \n" //3
448 "                in vec3 normal,                                            \n" //4
449 "                inout vec4 ambient,                                        \n" //5
450 "                inout vec4 diffuse,                                        \n" //6
451 "                inout vec4 specular)                                       \n" //7
452 "{                                                                          \n" //8
453 "    float nDotVP;      // normal . light direction                         \n" //9
454 "    float nDotHV;      // normal . light half vector                       \n" //10
455 "    float pf;          // power factor                                     \n" //11
456 "    float attenuation; // computed attenuation factor                      \n" //12
457 "    float d;           // distance from surface to light source            \n" //13
458 "    vec3  VP;          // direction from surface to light position         \n" //14
459 "    vec3  halfVector;  // direction of maximum highlights                  \n" //15
460 "                                                                           \n" //16
461 "    // Compute vector from surface to light position                       \n" //17
462 "    VP = vec3(gl_LightSource[i].position) - position;                      \n" //18
463 "                                                                           \n" //19
464 "    // Compute distance between surface and light position                 \n" //20
465 "    d = length(VP);                                                        \n" //21
466 "                                                                           \n" //22
467 "    // Normalize the vector from surface to light position                 \n" //23
468 "    VP = normalize(VP);                                                    \n" //24
469 "                                                                           \n" //25
470 "    // Compute attenuation                                                 \n" //26
471 "    attenuation = 1.0 / (gl_LightSource[i].constantAttenuation +           \n" //27
472 "                         gl_LightSource[i].linearAttenuation * d +         \n" //28
473 "                         gl_LightSource[i].quadraticAttenuation * d*d);    \n" //29
474 "                                                                           \n" //30
475 "    halfVector = normalize(VP + eye);                                      \n" //31
476 "                                                                           \n" //32
477 "    nDotVP = max(0.0, dot(normal, VP));                                    \n" //33
478 "    nDotHV = max(0.0, dot(normal, halfVector));                            \n" //34
479 "                                                                           \n" //35
480 "    if (nDotVP == 0.0)                                                     \n" //36
481 "        pf = 0.0;                                                          \n" //37
482 "    else                                                                   \n" //38
483 "        pf = pow(nDotHV, gl_FrontMaterial.shininess);                      \n" //39
484 "                                                                           \n" //40
485 "    ambient += gl_LightSource[i].ambient * attenuation;                    \n" //41
486 "    diffuse += gl_LightSource[i].diffuse * nDotVP * attenuation;           \n" //42
487 "    specular += gl_LightSource[i].specular * pf * attenuation;             \n" //43
488 "}                                                                          \n";//44
489 
490 char DirectionalLightShaderSource[] =
491 "void DirectionalLight(in int i,                                            \n" //1
492 "                      in vec3 normal,                                      \n" //2
493 "                      inout vec4 ambient,                                  \n" //3
494 "                      inout vec4 diffuse,                                  \n" //4
495 "                      inout vec4 specular)                                 \n" //5
496 "{                                                                          \n" //6
497 "     float nDotVP;         // normal . light direction                     \n" //7
498 "     float nDotHV;         // normal . light half vector                   \n" //8
499 "     float pf;             // power factor                                 \n" //9
500 "                                                                           \n" //10
501 "     nDotVP = max(0.0, dot(normal,                                         \n" //11
502 "                normalize(vec3(gl_LightSource[i].position))));             \n" //12
503 "     nDotHV = max(0.0, dot(normal,                                         \n" //13
504 "                      vec3(gl_LightSource[i].halfVector)));                \n" //14
505 "                                                                           \n" //15
506 "     if (nDotVP == 0.0)                                                    \n" //16
507 "         pf = 0.0;                                                         \n" //17
508 "     else                                                                  \n" //18
509 "         pf = pow(nDotHV, gl_FrontMaterial.shininess);                     \n" //19
510 "                                                                           \n" //20
511 "     ambient  += gl_LightSource[i].ambient;                                \n" //21
512 "     diffuse  += gl_LightSource[i].diffuse * nDotVP;                       \n" //22
513 "     specular += gl_LightSource[i].specular * pf;                          \n" //23
514 "}                                                                          \n";//24
515 
516