## Public API Reference

- Main Page
- Modules
- Namespaces
- Classes
- Files
- Related Pages

- File List
- File Members

# 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__