|
@@ -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;
|
|
|
|
|
|
-}
|
|
|
+}
|