Browse Source

Update to ShadowMap

-Now is editable from script to change colour, radius and segments
-Raycast list is simplified down to only rays that are necessary to improve runtime
marauder2k7 5 years ago
parent
commit
603f6a390f

+ 60 - 103
engine/source/2d/sceneobject/ShadowMap.cc

@@ -8,8 +8,12 @@
 
 IMPLEMENT_CONOBJECT(ShadowMap);
 
-ShadowMap::ShadowMap()
+ShadowMap::ShadowMap():
+   mLightRadius(10.0f),
+   mLightSegments(15)
 {
+   mSrcBlendFactor = GL_SRC_ALPHA;
+   mDstBlendFactor = GL_ONE;
    // Use a static body by default.
    mBodyDefinition.type = b2_staticBody;
 }
@@ -40,6 +44,11 @@ void ShadowMap::onRemove()
 void ShadowMap::initPersistFields()
 {
    Parent::initPersistFields();
+
+   /// Light settings.
+   addProtectedField("LightRadius", TypeF32, Offset(mLightRadius, ShadowMap), &setLightRadius, &defaultProtectedGetFn, &writeLightRadius, "");
+   addProtectedField("LightSegments", TypeS32, Offset(mLightSegments, ShadowMap), &setLightSegments, &defaultProtectedGetFn, &writeLightSegments, "");
+
 }
 
 void ShadowMap::safeDelete(void)
@@ -52,25 +61,31 @@ void ShadowMap::sceneRender(const SceneRenderState * sceneRenderState, const Sce
    Vector2 worldPos = getPosition();
    Vector<Vector2> verts;
    Vector<RayList> bList;
+   S32 mSrcLightBlend = getSrcBlendFactor();
+   S32 mDstLightBlend = getDstBlendFactor();
+   ColorF mLightColor = getBlendColor();
 
-
-   F32 radius = getSize().x * 0.5f;
+   F32 radius = getLightRadius();
    Scene* scene = getScene();
    b2World* mWorld = scene->getWorld();
 
+
+   
+
    glEnable(GL_BLEND);
-   //glDisable(GL_TEXTURE_2D);
+   glDisable(GL_TEXTURE_2D);
    glPushMatrix();
+ 
    glTranslatef(worldPos.x, worldPos.y, 0);
    glPolygonMode(GL_FRONT, GL_FILL);
 
    //additive blending
    //glBlendFunc(GL_ONE,GL_ONE);
-
-   glBlendFunc(GL_DST_COLOR, GL_ONE);
+   
+   glBlendFunc(mSrcLightBlend, mDstLightBlend);
    // Creates the fading dark region.
    glBegin(GL_TRIANGLE_FAN);
-   glColor4f(1, 1, 1, 1);
+   glColor4f(mLightColor.red,mLightColor.green,mLightColor.blue,mLightColor.alpha);
    glVertex2f(0, 0);
    //check scene objects
    U32 objCount = scene->getSceneObjectCount();
@@ -86,7 +101,7 @@ void ShadowMap::sceneRender(const SceneRenderState * sceneRenderState, const Sce
          U32 shapeCount = tObj->getCollisionShapeCount();
          for (U32 j = 0; j < shapeCount; j++)
          {
-            //All vertices from collision shape
+            //All vertices from polygon collision shape
             if (tObj->getCollisionShapeType(j) == b2Shape::e_polygon)
             {
                U32 pCount = tObj->getPolygonCollisionShapePointCount(j);
@@ -101,14 +116,17 @@ void ShadowMap::sceneRender(const SceneRenderState * sceneRenderState, const Sce
          }
       }
    }
-   //  \ | /
-   // -  +  -
-   //  / | \
+   ///  \ | /
+   /// -  +  -
+   ///  / | \
+
+   U32 lightSeg = getLightSegments();
+   F32 segAng = 360.0f / lightSeg;
 
-   for (U32 i = 0; i <= 12; i++)
+   for (U32 i = 0; i <= lightSeg; i++)
    {
       b2Vec2 segStrt = worldPos;
-      b2Vec2 segEnd = segStrt + radius * b2Vec2(mCos(mDegToRad((F32)30 * i)), mSin(mDegToRad((F32)30 * i)));
+      b2Vec2 segEnd = segStrt + radius * b2Vec2(mCos(mDegToRad((F32)segAng * i)), mSin(mDegToRad((F32)segAng * i)));
       verts.push_back(segEnd);
    }
 
@@ -120,11 +138,11 @@ void ShadowMap::sceneRender(const SceneRenderState * sceneRenderState, const Sce
       Vector2 p2 = verts[l];
       F32 baseAng = mAtan(p2.x, p2.y);
       F32 cAng = 0;
-      for (int m = 0; m < 3; m++)
+      for (int m = 0; m < 2; m++)
       {
          if (m == 0)cAng = baseAng - 0.0001f;
-         if (m == 1)cAng = baseAng;
-         if (m == 2)cAng = baseAng + 0.0001f;
+         //if (m == 1)cAng = baseAng;
+         if (m == 1)cAng = baseAng + 0.0001f;
 
          p2.x = rayLength * mCos(cAng);
          p2.y = rayLength * mSin(cAng);
@@ -143,7 +161,8 @@ void ShadowMap::sceneRender(const SceneRenderState * sceneRenderState, const Sce
             intersectionPoint.y = intersection.y;
             intersectionPoint.l = callback.m_fraction;
 
-            bList.push_back(intersectionPoint);
+
+            bList.push_back_unique(intersectionPoint);
 
          }
          else
@@ -156,46 +175,43 @@ void ShadowMap::sceneRender(const SceneRenderState * sceneRenderState, const Sce
             intersectionPoint.y = p2.y;
             intersectionPoint.l = 1.0;
 
-            bList.push_back(intersectionPoint);
+            bList.push_back_unique(intersectionPoint);
          }
       }
    }
-   
+
+   //Con::printf("Rays cast: %i", bList.size());
+   //unique the list
+   /*if (bList.size() > 1)
+   {
+      dQsort(bList.address(), bList.size(), sizeof(RayList), uniqueRays);
+   }*/
+
+   //Con::printf("Rays cast: %i", bList.size());
    //sort the list
    if (bList.size() > 1)
    {
       dQsort(bList.address(), bList.size(), sizeof(RayList), sortRays);
    }
+
+   
+
    //triangle fan
    for (S32 m = 0; m < bList.size(); m++)
    {
-      glColor4f(1.0 - bList[m].l , 1.0 - bList[m].l , 1.0 - bList[m].l , 1.0 - bList[m].l);
+      glColor4f(mLightColor.red - (mLightColor.red * bList[m].l), mLightColor.green - (mLightColor.green * bList[m].l), mLightColor.blue - (mLightColor.blue * bList[m].l), mLightColor.alpha - (mLightColor.alpha * bList[m].l));
       glVertex2f(bList[m].x, bList[m].y);
 
    }
    //close off the circle
-   glColor4f(1.0 - bList[0].l, 1.0 - bList[0].l, 1.0 - bList[0].l, 1.0 - bList[0].l);
+   glColor4f(mLightColor.red - (mLightColor.red * bList[0].l), mLightColor.green - (mLightColor.green * bList[0].l), mLightColor.blue - (mLightColor.blue * bList[0].l), mLightColor.alpha - (mLightColor.alpha * bList[0].l));
    glVertex2f(bList[0].x, bList[0].y);
 
-   glEnd();
-
-
-   /*U32 shadObj = scene->getSceneObjectCount();
-   for (U32 i = 0; i < shadObj; i++)
-   {
-      SceneObject *sObj = scene->getSceneObject(i);
-      Vector2 distancePos = worldPos - sObj->getPosition();
+   glDisable(GL_BLEND);
 
-      const F32 distanceSqr = distancePos.LengthSquared();
-      const F32 radiusSqr = radius * radius;
-      if (distanceSqr < radiusSqr || distanceSqr == radiusSqr)
-      {
-         processObject(sObj);
-      }
-   }*/
+   glEnd();
 
    glPopMatrix();
-
 }
 
 void ShadowMap::OnRegisterScene(Scene* mScene)
@@ -213,87 +229,28 @@ void ShadowMap::OnUnregisterScene(Scene* mScene)
 
 void ShadowMap::processObject(SceneObject *obj)
 {
-   Vector2 pos = getPosition();
-   Vector<Vector2> verts;
-   U32 shapeCount = obj->getCollisionShapeCount();
-   for (U32 i = 0; i < shapeCount; i++)
-   {
-      if (obj->getCollisionShapeType(i) == b2Shape::e_polygon)
-      {
-         U32 pointCount = obj->getPolygonCollisionShapePointCount(i);
-         for (U32 n = 0; n < pointCount; n++)
-         {
-            Vector2 locPoint = obj->getPolygonCollisionShapeLocalPoint(i, n);
-            Vector2 wPoint = obj->getWorldPoint(locPoint);
-
-            verts.push_back(wPoint);
-         }
 
-         renderShadow(verts, pos);
-      }
-   }
 }
 
-void ShadowMap::renderShadow(const Vector<Vector2>& verts, const Vector2& lightPos)
+void ShadowMap::renderShadow(const Vector<RayList>& verts, const Vector2& lightPos)
 {
-   S32 startVert = 0;
-   S32 endVert = 0;
-   for (S32 i = 1; i < verts.size() + 1; i++)
-   {
-      S32 vert0 = (i - 1) % verts.size();
-      S32 vert1 = (i) % verts.size();
-      S32 vert2 = (i + 1) % verts.size();
-      Vector2 normal0(verts[vert0] - verts[vert1]);
-      normal0.perp();
-      Vector2 normal1(verts[vert1] - verts[vert2]);
-      normal1.perp();
-      Vector2 ray(verts[vert1] - lightPos);
-      F32 n0 = ray.dot(normal0);
-      F32 n1 = ray.dot(normal1);
-      if (n0 <= 0 && n1 > 0)
-      {
-         startVert = vert1;
-      }
-      if (n0 > 0 && n1 <= 0)
-      {
-         endVert = vert1;
-      }
-   }
-   glEnable(GL_BLEND);
-   glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-   //glDisable(GL_TEXTURE_2D);
-   glColor4f(0, 0, 0, 0.5);
-   glBegin(GL_TRIANGLE_STRIP);
-   for (S32 i = 0; i < verts.size(); i++)
-   {
-      S32 vert = (startVert + i) % verts.size();
-      Vector2 ray(verts[vert] - lightPos); ray.Normalize(600.0f);
-      glVertex2f(verts[vert].x, verts[vert].y);
-      glColor4f(0, 0, 0, 0.1);
-      glVertex2f(verts[vert].x + ray.x, verts[vert].y + ray.y);
-      if (vert == endVert) break;
-   }
-   //glVertex2f(verts[0].x, verts[0].y);
-   //glVertex2f(verts[1].x, verts[1].y);
-   //glVertex2f(lightPos.x, lightPos.y);
-   //glVertex2f(verts[3].x, verts[3].y);
-   glEnd();
+
 }
 
 S32 QSORT_CALLBACK sortRays(const void* a, const void* b)
 {
-   RayList* ang_a = (RayList*) a;
-   RayList* ang_b = (RayList*) b;
+   RayList* ray_a = (RayList*) a;
+   RayList* ray_b = (RayList*) b;
 
-   if (ang_a->ang < ang_b->ang)
+   if (ray_a->ang < ray_b->ang)
    {
       return -1;
    }
-   else if (ang_a->ang > ang_b->ang)
+   else if (ray_a->ang > ray_b->ang)
    {
       return 1;
    }
   
    return 0;
 
-}
+}

+ 26 - 11
engine/source/2d/sceneobject/ShadowMap.h

@@ -5,14 +5,16 @@
 #include "2d/sceneobject/SceneObject.h"
 #endif
 
-struct RayList
+class RayList
 {
-   F32 ang;
+public:
+
    F32 x;
    F32 y;
    F32 l;
+   F32 ang;
+   bool operator == (const RayList& t) const { return ((mFabs(t.x - x) < 0.01) && (mFabs(t.y - y) < 0.01)); }
 };
-
 class RaysCastCallback : public b2RayCastCallback
 {
 public:
@@ -40,7 +42,8 @@ class ShadowMap : public SceneObject
    typedef SceneObject Parent;
 
 protected:
-   F32            mLightRadius;
+   F32                     mLightRadius;
+   U32                     mLightSegments;
 
 public:
    ShadowMap();
@@ -48,8 +51,7 @@ public:
 
    static void initPersistFields();
 
-   inline void setLightRadius(const F32 lightRadius) { mLightRadius = lightRadius; }
-   inline F32 getLightRadius(void) const { return mLightRadius; }
+   
 
    virtual bool onAdd();
    virtual void onRemove();
@@ -60,21 +62,34 @@ public:
    virtual bool shouldRender(void) const { return true; }
 
    void processObject(SceneObject *obj);
-   void renderShadow(const Vector<Vector2>& verts, const Vector2& lightPos);
+   void renderShadow(const Vector<RayList>& verts, const Vector2& lightPos);
+
+   /// Light segments.
+   inline void             setLightSegments(const U32 lightSegments) { mLightSegments = lightSegments; };
+   inline U32              getLightSegments(void) const { return mLightSegments; }
+
+   /// Light Radius.
+   inline void setLightRadius(const F32 lightRadius) { mLightRadius = lightRadius; }
+   inline F32 getLightRadius(void) const { return mLightRadius; }
 
    DECLARE_CONOBJECT(ShadowMap);
 
 
-   protected:
+protected:
       virtual void OnRegisterScene(Scene* mScene);
       virtual void OnUnregisterScene(Scene* mScene);
 
-private:
-   F32 theSinTable[361];
-   F32 theCosTable[361];
+protected:
+   static bool setLightRadius(void* obj, const char* data) { static_cast<ShadowMap*>(obj)->setLightRadius(dAtof(data)); return false; }
+   static bool writeLightRadius(void* obj, StringTableEntry pFieldName) { return static_cast<ShadowMap*>(obj)->getLightRadius() > 0.0f; }
+
+   static bool setLightSegments(void* obj, const char* data) { static_cast<ShadowMap*>(obj)->setLightSegments(dAtoi(data)); return false; }
+   static bool writeLightSegments(void* obj, StringTableEntry pFieldName) { return static_cast<ShadowMap*>(obj)->getLightSegments() > 0; }
+
 };
 
 
 #endif //_SHADOWMAP_H_
 
 S32 QSORT_CALLBACK sortRays(const void * a, const void * b);
+S32 QSORT_CALLBACK uniqueRays(const void * a, const void * b);

+ 52 - 1
engine/source/2d/sceneobject/ShadowMap_ScriptBinding.h

@@ -1 +1,52 @@
-#pragma once
+//-----------------------------------------------------------------------------
+// Copyright (c) 2013 GarageGames, LLC
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to
+// deal in the Software without restriction, including without limitation the
+// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+// sell copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+// IN THE SOFTWARE.
+//-----------------------------------------------------------------------------
+ConsoleMethodGroupBeginWithDocs(ShadowMap, SceneObject)
+
+/*! Add the object to a scene.
+    @param scene the scene you wish to add this object to.
+    @return No return value.
+*/
+
+ConsoleMethodWithDocs(ShadowMap, setLightRadius, ConsoleVoid, 3, 3, (float radius))
+{
+   // Set Lifetime.
+   object->setLightRadius(dAtof(argv[2]));
+}
+
+ConsoleMethodWithDocs(ShadowMap, getLightRadius, ConsoleFloat, 2, 2, ())
+{
+   // Return Lifetime.
+   return object->getLightRadius();
+}
+
+
+ConsoleMethodWithDocs(ShadowMap, setLightSegments, ConsoleVoid, 3, 3, (integer lightSegments))
+{
+   // Set Layer.
+   object->setLightSegments(dAtoi(argv[2]));
+}
+
+ConsoleMethodWithDocs(ShadowMap, getLightSegments, ConsoleInt, 2, 2, ())
+{
+   // Return Layer.
+   return object->getLightSegments();
+}

+ 4 - 3
engine/source/platformWin32/gl_types.h

@@ -159,6 +159,7 @@
 typedef unsigned int	GLenum;
 typedef unsigned char	GLboolean;
 typedef unsigned int	GLbitfield;
+typedef unsigned int GLuint; /* update ogl imp capabilities*/
 typedef void		GLvoid;
 typedef signed char	GLbyte;		/* 1-byte signed */
 typedef short		GLshort;	/* 2-byte signed */
@@ -474,9 +475,9 @@ typedef double		GLclampd;	/* double precision float in [0,1] */
 #define GL_NONE					0x0
 #define GL_LEFT					0x0406
 #define GL_RIGHT				0x0407
-/*GL_FRONT					0x0404 */
-/*GL_BACK					0x0405 */
-/*GL_FRONT_AND_BACK				0x0408 */
+/*#define GL_FRONT					0x0404 */
+/*#define GL_BACK					0x0405*/
+/*#define GL_FRONT_AND_BACK				0x0408 */
 #define GL_FRONT_LEFT				0x0400
 #define GL_FRONT_RIGHT				0x0401
 #define GL_BACK_LEFT				0x0402

+ 2 - 1
modules/PyramidToy/1/main.cs

@@ -193,6 +193,7 @@ function PyramidToy::createPyramid( %this )
 	%map = new ShadowMap();
 	%map.setSize("15 15");
 	%map.setBodyType(Static);
-	%map.SceneLayer = 14;
+	%map.SceneLayer = 13;
+	%map.setBlendColor(0.5,0.5,1.0,1.0);
 	SandboxScene.add(%map);
 }