d7fb9b29345940cc588668555e89023f447f934a
[occt.git] / src / Shaders / PhongShading.fs
1 // Created on: 2013-10-10
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 varying vec3 View;          //!< Direction to the viewer
17 varying vec3 Normal;        //!< Vertex normal in view space
18 varying vec4 Position;      //!< Vertex position in view space.
19 varying vec4 PositionWorld; //!< Vertex position in world space
20
21 vec3 Ambient;  //!< Ambient  contribution of light sources
22 vec3 Diffuse;  //!< Diffuse  contribution of light sources
23 vec3 Specular; //!< Specular contribution of light sources
24
25 //! Computes contribution of isotropic point light source
26 void pointLight (in int  theId,
27                  in vec3 theNormal,
28                  in vec3 theView,
29                  in vec3 thePoint)
30 {
31   vec3 aLight = occLight_Position (theId).xyz;
32   if (occLight_IsHeadlight (theId) == 0)
33   {
34     aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));
35   }
36   aLight -= thePoint;
37
38   float aDist = length (aLight);
39   aLight = aLight * (1.0 / aDist);
40
41   float anAtten = 1.0 / (occLight_ConstAttenuation  (theId)
42                        + occLight_LinearAttenuation (theId) * aDist);
43
44   vec3 aHalf = normalize (aLight + theView);
45
46   vec3  aFaceSideNormal = gl_FrontFacing ? theNormal : -theNormal;
47   float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));
48   float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));
49
50   float aSpecl = 0.0;
51   if (aNdotL > 0.0)
52   {
53     aSpecl = pow (aNdotH, gl_FrontFacing ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());
54   }
55
56   Diffuse  += occLight_Diffuse  (theId).rgb * aNdotL * anAtten;
57   Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;
58 }
59
60 //! Computes contribution of spotlight source
61 void spotLight (in int  theId,
62                 in vec3 theNormal,
63                 in vec3 theView,
64                 in vec3 thePoint)
65 {
66   vec3 aLight   = occLight_Position      (theId).xyz;
67   vec3 aSpotDir = occLight_SpotDirection (theId).xyz;
68   if (occLight_IsHeadlight (theId) == 0)
69   {
70     aLight   = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight,   1.0));
71     aSpotDir = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aSpotDir, 0.0));
72   }
73   aLight -= thePoint;
74
75   float aDist = length (aLight);
76   aLight = aLight * (1.0 / aDist);
77
78   aSpotDir = normalize (aSpotDir);
79
80   // light cone
81   float aCosA = dot (aSpotDir, -aLight);
82   if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))
83   {
84     return;
85   }
86
87   float anExponent = occLight_SpotExponent (theId);
88   float anAtten    = 1.0 / (occLight_ConstAttenuation  (theId)
89                           + occLight_LinearAttenuation (theId) * aDist);
90   if (anExponent > 0.0)
91   {
92     anAtten *= pow (aCosA, anExponent * 128.0);
93   }
94
95   vec3 aHalf = normalize (aLight + theView);
96
97   vec3  aFaceSideNormal = gl_FrontFacing ? theNormal : -theNormal;
98   float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));
99   float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));
100
101   float aSpecl = 0.0;
102   if (aNdotL > 0.0)
103   {
104     aSpecl = pow (aNdotH, gl_FrontFacing ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());
105   }
106
107   Diffuse  += occLight_Diffuse  (theId).rgb * aNdotL * anAtten;
108   Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;
109 }
110
111 //! Computes contribution of directional light source
112 void directionalLight (in int  theId,
113                        in vec3 theNormal,
114                        in vec3 theView)
115 {
116   vec3 aLight = normalize (occLight_Position (theId).xyz);
117   if (occLight_IsHeadlight (theId) == 0)
118   {
119     aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));
120   }
121
122   vec3 aHalf = normalize (aLight + theView);
123
124   vec3  aFaceSideNormal = gl_FrontFacing ? theNormal : -theNormal;
125   float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));
126   float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));
127
128   float aSpecl = 0.0;
129   if (aNdotL > 0.0)
130   {
131     aSpecl = pow (aNdotH, gl_FrontFacing ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());
132   }
133
134   Diffuse  += occLight_Diffuse  (theId).rgb * aNdotL;
135   Specular += occLight_Specular (theId).rgb * aSpecl;
136 }
137
138 //! Computes illumination from light sources
139 vec4 computeLighting (in vec3 theNormal,
140                       in vec3 theView,
141                       in vec4 thePoint)
142 {
143   // Clear the light intensity accumulators
144   Ambient  = occLightAmbient.rgb;
145   Diffuse  = vec3 (0.0);
146   Specular = vec3 (0.0);
147   vec3 aPoint = thePoint.xyz / thePoint.w;
148   for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)
149   {
150     int aType = occLight_Type (anIndex);
151     if (aType == OccLightType_Direct)
152     {
153       directionalLight (anIndex, theNormal, theView);
154     }
155     else if (aType == OccLightType_Point)
156     {
157       pointLight (anIndex, theNormal, theView, aPoint);
158     }
159     else if (aType == OccLightType_Spot)
160     {
161       spotLight (anIndex, theNormal, theView, aPoint);
162     }
163   }
164
165   vec4 aMaterialAmbient  = gl_FrontFacing ? occFrontMaterial_Ambient()  : occBackMaterial_Ambient();
166   vec4 aMaterialDiffuse  = gl_FrontFacing ? occFrontMaterial_Diffuse()  : occBackMaterial_Diffuse();
167   vec4 aMaterialSpecular = gl_FrontFacing ? occFrontMaterial_Specular() : occBackMaterial_Specular();
168   vec4 aMaterialEmission = gl_FrontFacing ? occFrontMaterial_Emission() : occBackMaterial_Emission();
169   return vec4 (Ambient,  1.0) * aMaterialAmbient
170        + vec4 (Diffuse,  1.0) * aMaterialDiffuse
171        + vec4 (Specular, 1.0) * aMaterialSpecular
172                               + aMaterialEmission;
173 }
174
175 //! Entry point to the Fragment Shader
176 void main()
177 {
178   // process clipping planes
179   for (int anIndex = 0; anIndex < occClipPlaneCount; ++anIndex)
180   {
181     vec4 aClipEquation = occClipPlaneEquations[anIndex];
182     int  aClipSpace    = occClipPlaneSpaces[anIndex];
183     if (aClipSpace == OccEquationCoords_World)
184     {
185       if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)
186       {
187         discard;
188       }
189     }
190     else if (aClipSpace == OccEquationCoords_View)
191     {
192       if (dot (aClipEquation.xyz, Position.xyz) + aClipEquation.w < 0.0)
193       {
194         discard;
195       }
196     }
197   }
198
199   gl_FragColor = computeLighting (normalize (Normal),
200                                   normalize (View),
201                                   Position);
202 }