CrystalSpace

Public API Reference

csgfx/vertexlight.h

Go to the documentation of this file.
00001 /*
00002   Copyright (C) 2005 by Marten Svanfeldt
00003 
00004   This library is free software; you can redistribute it and/or
00005   modify it under the terms of the GNU Library General Public
00006   License as published by the Free Software Foundation; either
00007   version 2 of the License, or (at your option) any later version.
00008 
00009   This library is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012   Library General Public License for more details.
00013 
00014   You should have received a copy of the GNU Library General Public
00015   License along with this library; if not, write to the Free
00016   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 */
00018 
00019 #ifndef __CS_CSGFX_VERTEXLIGHT_H__
00020 #define __CS_CSGFX_VERTEXLIGHT_H__
00021 
00022 #include "csqsqrt.h"
00023 #include "csgeom/math.h"
00024 #include "csgeom/transfrm.h"
00025 #include "csgeom/vector3.h"
00026 #include "csgfx/lightsvcache.h"
00027 #include "csutil/cscolor.h"
00028 #include "cstool/rbuflock.h"
00029 
00030 #include "iengine/light.h"
00031 #include "iengine/movable.h"
00032 #include "ivideo/shader/shader.h"
00033 
00041 struct CS_CRYSTALSPACE_EXPORT csLightProperties
00042 {
00044   csVector3 attenuationConsts;
00046   csVector3 posObject;
00051   csVector3 dirObject;
00053   csColor color;
00055   float spotFalloffInner;
00057   float spotFalloffOuter;
00059   csLightType type;
00061   csLightAttenuationMode attenuationMode;
00062 
00063   csLightProperties () : spotFalloffInner(0.0f), spotFalloffOuter(0.0f),
00064     type(CS_LIGHT_POINTLIGHT) {}
00069   csLightProperties (size_t lightNum, csLightShaderVarCache& svcache,
00070     const csShaderVarStack &stacks)
00071   {
00072     csStringID id;
00073 
00074     id = svcache.GetLightSVId (lightNum, 
00075       csLightShaderVarCache::lightAttenuation);
00076     if ((stacks.Length() > id) && (stacks[id] != 0))
00077       stacks[id]->GetValue (attenuationConsts);
00078 
00079     id = svcache.GetLightSVId (lightNum, 
00080       csLightShaderVarCache::lightPosition);
00081     if ((stacks.Length() > id) && (stacks[id] != 0))
00082       stacks[id]->GetValue (posObject);
00083 
00084     id = svcache.GetLightSVId (lightNum, 
00085       csLightShaderVarCache::lightDirection);
00086     if ((stacks.Length() > id) && (stacks[id] != 0))
00087       stacks[id]->GetValue (dirObject);
00088 
00089     id = svcache.GetLightSVId (lightNum, 
00090       csLightShaderVarCache::lightDiffuse);
00091     if ((stacks.Length() > id) && (stacks[id] != 0))
00092       stacks[id]->GetValue (color);
00093 
00094     id = svcache.GetLightSVId (lightNum, 
00095       csLightShaderVarCache::lightInnerFalloff);
00096     if ((stacks.Length() > id) && (stacks[id] != 0))
00097       stacks[id]->GetValue (spotFalloffInner);
00098 
00099     id = svcache.GetLightSVId (lightNum, 
00100       csLightShaderVarCache::lightOuterFalloff);
00101     if ((stacks.Length() > id) && (stacks[id] != 0))
00102       stacks[id]->GetValue (spotFalloffOuter);
00103 
00104     int t = CS_LIGHT_POINTLIGHT;
00105     id = svcache.GetLightSVId (lightNum, 
00106       csLightShaderVarCache::lightType);
00107     if ((stacks.Length() > id) && (stacks[id] != 0))
00108       stacks[id]->GetValue (t);
00109     type = (csLightType)t;
00110 
00111     t = CS_ATTN_NONE;
00112     id = svcache.GetLightSVId (lightNum, 
00113       csLightShaderVarCache::lightAttenuationMode);
00114     if ((stacks.Length() > id) && (stacks[id] != 0))
00115       stacks[id]->GetValue (t);
00116     attenuationMode = (csLightAttenuationMode)t;
00117   }
00118 };
00119 
00123 struct CS_CRYSTALSPACE_EXPORT csNoAttenuation
00124 {
00125   csNoAttenuation (const csLightProperties& /*light*/)
00126   {}
00127 
00128   CS_FORCEINLINE void operator() (float /*distance*/, float & /*dp*/) const
00129   {}
00130 };
00131 
00136 struct CS_CRYSTALSPACE_EXPORT csLinearAttenuation
00137 {
00138   csLinearAttenuation (const csLightProperties& light)
00139   {
00140     invrad = 1/light.attenuationConsts.x;
00141   }
00142 
00143   CS_FORCEINLINE void operator() (float distance, float& dp) const
00144   {
00145     dp = csMax (dp * (1 - distance * invrad), 0.0f);
00146   }
00147 
00148   float invrad;
00149 };
00150 
00155 struct CS_CRYSTALSPACE_EXPORT csInverseAttenuation
00156 {
00157   csInverseAttenuation (const csLightProperties& /*light*/)
00158   {}
00159 
00160   CS_FORCEINLINE void operator() (float distance, float& dp) const
00161   {
00162     dp = dp / distance;
00163   }
00164 };
00165 
00166 
00171 struct CS_CRYSTALSPACE_EXPORT csRealisticAttenuation
00172 {
00173   csRealisticAttenuation (const csLightProperties& /*light*/)
00174   {}
00175 
00176   CS_FORCEINLINE void operator() (float distance, float& dp) const
00177   {
00178     dp = dp / (distance*distance);
00179   }
00180 };
00181 
00186 struct CS_CRYSTALSPACE_EXPORT csCLQAttenuation
00187 {
00188   csCLQAttenuation (const csLightProperties& light)
00189     : attnVec (light.attenuationConsts)
00190   {}
00191 
00192   CS_FORCEINLINE void operator() (float distance, float& dp) const
00193   {
00194     dp = dp/(csVector3 (1.0, distance, distance*distance)*attnVec);
00195   }
00196 
00197   csVector3 attnVec;
00198 };
00199 
00200 
00206 template<class AttenuationProc>
00207 class csPointLightProc
00208 {
00209 public:
00210   csPointLightProc (const csLightProperties& light, 
00211     float blackLimit = 0.0001f)
00212     : attn (light), nullColor (0.0f, 0.0f, 0.0f), blackLimit (blackLimit)
00213   {    
00214     lightPos = light.posObject;
00215     lightCol = light.color;
00216   }
00217 
00218   CS_FORCEINLINE
00219   csColor ProcessVertex (const csVector3 &v,const csVector3 &n) const
00220   {
00221     //compute gouraud shading..
00222     csVector3 direction = lightPos-v;
00223     float distance = csQsqrt(direction.SquaredNorm ());
00224     float dp = (direction*n)/distance;
00225     if (dp > blackLimit)
00226     {
00227       attn (distance, dp);
00228       return lightCol*dp;
00229     }
00230     return nullColor;
00231   }
00232 
00233 private:
00234   AttenuationProc attn;
00235   csVector3 lightPos; //localspace
00236   csColor lightCol;
00237   csColor nullColor;
00238   float blackLimit;
00239 };
00240 
00246 template<class AttenuationProc>
00247 class csDirectionalLightProc
00248 {
00249 public:
00250   csDirectionalLightProc (const csLightProperties& light, 
00251     float blackLimit = 0.0001f)
00252     : attn (light), nullColor (0.0f, 0.0f, 0.0f), blackLimit (blackLimit)
00253   {
00254     lightPos = light.posObject;
00255     lightDir = light.dirObject;
00256     lightCol = light.color;
00257   }
00258 
00259   CS_FORCEINLINE
00260   csColor ProcessVertex (const csVector3 &v,const csVector3 &n) const
00261   {
00262     //compute gouraud shading..
00263     float dp = -lightDir*n;
00264     if (dp > blackLimit)
00265     {
00266       csVector3 direction = lightPos-v;
00267       float distance = csQsqrt(direction.SquaredNorm ());
00268       attn (distance, dp);
00269       return lightCol*dp;
00270     }
00271     return nullColor;
00272   }
00273 
00274 private:
00275   AttenuationProc attn;
00276   csVector3 lightPos; //localspace
00277   csVector3 lightDir; //localspace
00278   csColor lightCol;
00279   csColor nullColor;
00280   float blackLimit;
00281 };
00282 
00288 template<class AttenuationProc>
00289 class csSpotLightProc
00290 {
00291 public:
00292   csSpotLightProc (const csLightProperties& light, 
00293     float blackLimit = 0.0001f)
00294     : attn (light), nullColor (0.0f, 0.0f, 0.0f), blackLimit (blackLimit)
00295   {
00296     lightPos = light.posObject;
00297     lightDir = light.dirObject;
00298 
00299     lightCol = light.color;
00300     falloffInner = light.spotFalloffInner;
00301     falloffOuter = light.spotFalloffOuter;
00302   }
00303 
00304   CS_FORCEINLINE
00305   csColor ProcessVertex (const csVector3 &v,const csVector3 &n) const
00306   {
00307     csVector3 direction = (lightPos-v).Unit ();
00308 
00309     //compute gouraud shading..
00310     float dp = direction*n;
00311     if (dp > blackLimit)
00312     {
00313       float cosfact =
00314         csSmoothStep (-(direction*lightDir), falloffInner, falloffOuter);
00315       float distance = csQsqrt(direction.SquaredNorm ());
00316       if (cosfact > 0)
00317       {
00318         attn (distance, dp);
00319         return lightCol*dp*cosfact;
00320       }
00321     }
00322     return nullColor;
00323   }
00324 
00325 private:
00326   AttenuationProc attn;
00327   csVector3 lightPos; //localspace
00328   csVector3 lightDir; //localspace
00329   csColor lightCol;
00330   csColor nullColor;
00331   float blackLimit;
00332   float falloffInner, falloffOuter;
00333 };
00334 
00338 struct iVertexLightCalculator
00339 {
00340 public:
00349   virtual void CalculateLighting (const csLightProperties& light, 
00350     size_t numvert, iRenderBuffer* vb, iRenderBuffer* nb, 
00351     csColor *litColor) const = 0;
00352 
00357   virtual void CalculateLightingAdd (const csLightProperties& light, 
00358     size_t numvert, iRenderBuffer* vb, iRenderBuffer* nb, 
00359     csColor *litColor) const = 0;
00360 
00365   virtual void CalculateLightingMul (const csLightProperties& light, 
00366     size_t numvert, iRenderBuffer* vb, iRenderBuffer* nb, 
00367     csColor *litColor) const = 0;
00368 };
00369 
00375 template<class LightProc>
00376 class csVertexLightCalculator : public iVertexLightCalculator
00377 {
00378 public:
00379   virtual void CalculateLighting (const csLightProperties& light, 
00380     size_t numvert, iRenderBuffer* vb, iRenderBuffer* nb, 
00381     csColor *litColor) const
00382   {
00383     // setup the light calculator
00384     LightProc lighter (light);
00385     csRenderBufferLock<csVector3, iRenderBuffer*> vbLock (vb);
00386     csRenderBufferLock<csVector3, iRenderBuffer*> nbLock (nb);
00387 
00388     for (size_t n = 0; n < numvert; n++)
00389     {
00390       litColor[n] = lighter.ProcessVertex (vbLock[n], nbLock[n]);
00391     }
00392   }
00393 
00394   virtual void CalculateLightingAdd (const csLightProperties& light, 
00395     size_t numvert, iRenderBuffer* vb, iRenderBuffer* nb, 
00396     csColor *litColor) const
00397   {
00398     // setup the light calculator
00399     LightProc lighter (light);
00400     csRenderBufferLock<csVector3, iRenderBuffer*> vbLock (vb);
00401     csRenderBufferLock<csVector3, iRenderBuffer*> nbLock (nb);
00402 
00403 
00404     for (size_t n = 0; n < numvert; n++)
00405     {
00406       litColor[n] += lighter.ProcessVertex (vbLock[n], nbLock[n]);
00407     }
00408   }
00409 
00410   virtual void CalculateLightingMul (const csLightProperties& light, 
00411     size_t numvert, iRenderBuffer* vb, iRenderBuffer* nb, 
00412     csColor *litColor) const
00413   {
00414     // setup the light calculator
00415     LightProc lighter (light);
00416     csRenderBufferLock<csVector3, iRenderBuffer*> vbLock (vb);
00417     csRenderBufferLock<csVector3, iRenderBuffer*> nbLock (nb);
00418 
00419 
00420     for (size_t n = 0; n < numvert; n++)
00421     {
00422       litColor[n] *= lighter.ProcessVertex (vbLock[n], nbLock[n]);
00423     }
00424   }
00425 };
00426 
00427 #endif //__CS_VERTEXLIGHT_H__

Generated for Crystal Space by doxygen 1.4.6