0027925: Visualization - implement order-independent transparency algorithm within...
[occt.git] / src / Shaders / PhongShading.fs
old mode 100644 (file)
new mode 100755 (executable)
index 1b0779f..15311c7
@@ -1,25 +1,22 @@
 // Created on: 2013-10-10
 // Created by: Denis BOGOLEPOV
-// Copyright (c) 2013 OPEN CASCADE SAS
+// Copyright (c) 2013-2014 OPEN CASCADE SAS
 //
-// The content of this file is subject to the Open CASCADE Technology Public
-// License Version 6.5 (the "License"). You may not use the content of this file
-// except in compliance with the License. Please obtain a copy of the License
-// at http://www.opencascade.org and read it completely before using this file.
+// This file is part of Open CASCADE Technology software library.
 //
-// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
-// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
 //
-// The Original Code and all software distributed under the License is
-// distributed on an "AS IS" basis, without warranty of any kind, and the
-// Initial Developer hereby disclaims all such warranties, including without
-// limitation, any warranties of merchantability, fitness for a particular
-// purpose or non-infringement. Please see the License for the specific terms
-// and conditions governing the rights and limitations under the License.
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
 
-varying vec3 View;     //!< Direction to the viewer
-varying vec3 Normal;   //!< Vertex normal in view space
-varying vec4 Position; //!< Vertex position in view space.
+varying vec3 View;          //!< Direction to the viewer
+varying vec3 Normal;        //!< Vertex normal in view space
+varying vec4 Position;      //!< Vertex position in view space.
+varying vec4 PositionWorld; //!< Vertex position in world space
 
 vec3 Ambient;  //!< Ambient  contribution of light sources
 vec3 Diffuse;  //!< Diffuse  contribution of light sources
@@ -34,7 +31,7 @@ void pointLight (in int  theId,
   vec3 aLight = occLight_Position (theId).xyz;
   if (occLight_IsHeadlight (theId) == 0)
   {
-    aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));
+    aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));
   }
   aLight -= thePoint;
 
@@ -46,13 +43,65 @@ void pointLight (in int  theId,
 
   vec3 aHalf = normalize (aLight + theView);
 
-  float aNdotL = max (0.0, dot (theNormal, aLight));
-  float aNdotH = max (0.0, dot (theNormal, aHalf ));
+  vec3  aFaceSideNormal = gl_FrontFacing ? theNormal : -theNormal;
+  float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));
+  float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));
 
   float aSpecl = 0.0;
   if (aNdotL > 0.0)
   {
-    aSpecl = pow (aNdotH, occFrontMaterial_Shininess());
+    aSpecl = pow (aNdotH, gl_FrontFacing ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());
+  }
+
+  Diffuse  += occLight_Diffuse  (theId).rgb * aNdotL * anAtten;
+  Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;
+}
+
+//! Computes contribution of spotlight source
+void spotLight (in int  theId,
+                in vec3 theNormal,
+                in vec3 theView,
+                in vec3 thePoint)
+{
+  vec3 aLight   = occLight_Position      (theId).xyz;
+  vec3 aSpotDir = occLight_SpotDirection (theId).xyz;
+  if (occLight_IsHeadlight (theId) == 0)
+  {
+    aLight   = vec3 (occWorldViewMatrix * vec4 (aLight,   1.0));
+    aSpotDir = vec3 (occWorldViewMatrix * vec4 (aSpotDir, 0.0));
+  }
+  aLight -= thePoint;
+
+  float aDist = length (aLight);
+  aLight = aLight * (1.0 / aDist);
+
+  aSpotDir = normalize (aSpotDir);
+
+  // light cone
+  float aCosA = dot (aSpotDir, -aLight);
+  if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))
+  {
+    return;
+  }
+
+  float anExponent = occLight_SpotExponent (theId);
+  float anAtten    = 1.0 / (occLight_ConstAttenuation  (theId)
+                          + occLight_LinearAttenuation (theId) * aDist);
+  if (anExponent > 0.0)
+  {
+    anAtten *= pow (aCosA, anExponent * 128.0);
+  }
+
+  vec3 aHalf = normalize (aLight + theView);
+
+  vec3  aFaceSideNormal = gl_FrontFacing ? theNormal : -theNormal;
+  float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));
+  float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));
+
+  float aSpecl = 0.0;
+  if (aNdotL > 0.0)
+  {
+    aSpecl = pow (aNdotH, gl_FrontFacing ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());
   }
 
   Diffuse  += occLight_Diffuse  (theId).rgb * aNdotL * anAtten;
@@ -67,17 +116,19 @@ void directionalLight (in int  theId,
   vec3 aLight = normalize (occLight_Position (theId).xyz);
   if (occLight_IsHeadlight (theId) == 0)
   {
-    aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));
+    aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));
   }
 
   vec3 aHalf = normalize (aLight + theView);
-  float aNdotL = max (0.0, dot (theNormal, aLight));
-  float aNdotH = max (0.0, dot (theNormal, aHalf ));
+
+  vec3  aFaceSideNormal = gl_FrontFacing ? theNormal : -theNormal;
+  float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));
+  float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));
 
   float aSpecl = 0.0;
   if (aNdotL > 0.0)
   {
-    aSpecl = pow (aNdotH, occFrontMaterial_Shininess());
+    aSpecl = pow (aNdotH, gl_FrontFacing ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());
   }
 
   Diffuse  += occLight_Diffuse  (theId).rgb * aNdotL;
@@ -107,19 +158,42 @@ vec4 computeLighting (in vec3 theNormal,
     }
     else if (aType == OccLightType_Spot)
     {
-      // Not implemented
+      spotLight (anIndex, theNormal, theView, aPoint);
     }
   }
 
-  return vec4 (Ambient,  1.0) * occFrontMaterial_Ambient()
-       + vec4 (Diffuse,  1.0) * occFrontMaterial_Diffuse()
-       + vec4 (Specular, 1.0) * occFrontMaterial_Specular();
+  vec4 aMaterialAmbient  = gl_FrontFacing ? occFrontMaterial_Ambient()  : occBackMaterial_Ambient();
+  vec4 aMaterialDiffuse  = gl_FrontFacing ? occFrontMaterial_Diffuse()  : occBackMaterial_Diffuse();
+  vec4 aMaterialSpecular = gl_FrontFacing ? occFrontMaterial_Specular() : occBackMaterial_Specular();
+  vec4 aMaterialEmission = gl_FrontFacing ? occFrontMaterial_Emission() : occBackMaterial_Emission();
+  vec3 aColor = Ambient  * aMaterialAmbient.rgb
+              + Diffuse  * aMaterialDiffuse.rgb
+              + Specular * aMaterialSpecular.rgb
+                         + aMaterialEmission.rgb;
+  return vec4 (aColor, aMaterialDiffuse.a);
 }
 
 //! Entry point to the Fragment Shader
 void main()
 {
-  gl_FragColor = computeLighting (normalize (Normal),
+  // process clipping planes
+  for (int anIndex = 0; anIndex < occClipPlaneCount; ++anIndex)
+  {
+    vec4 aClipEquation = occClipPlaneEquations[anIndex];
+    if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)
+    {
+      discard;
+    }
+  }
+
+  occFragColor = computeLighting (normalize (Normal),
                                   normalize (View),
                                   Position);
+
+  if (occOitOutput != 0)
+  {
+    float aWeight     = occFragColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);
+    occFragCoverage.r = occFragColor.a * aWeight;
+    occFragColor      = vec4 (occFragColor.rgb * occFragColor.a * aWeight, occFragColor.a);
+  }
 }