Skip to content

Instantly share code, notes, and snippets.

@Shaptic
Created October 1, 2012 01:46
Show Gist options
  • Save Shaptic/3809002 to your computer and use it in GitHub Desktop.
Save Shaptic/3809002 to your computer and use it in GitHub Desktop.
Render shadows in OpenGL
void RenderShadows(const math::CVector2& LightPos),
const std::vector<Object*>& shadowCastingObjects)
{
// Set up rendering modes
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
glDisable(GL_BLEND);
glColor4f(0.3f, 0.3f, 0.3f, 1.0f); // Dark gray
for(size_t i = 0; i < shadowCastingObjects.size(); ++i)
{
math::CRay2 TopLeft, TopRight, BottomRight, BottomLeft;
TopLeft.Start = LightPos;
TopLeft.End = shadowCastingObjects[i]->GetPosition();
TopRight.Start = LightPos;
TopRight.End.x = shadowCastingObjects[i]->GetX() + shadowCastingObjects[i]->GetW();
TopRight.End.y = shadowCastingObjects[i]->GetY();
BottomRight.Start = LightPos;
BottomRight.End.x = shadowCastingObjects[i]->GetX() + shadowCastingObjects[i]->GetW();
BottomRight.End.y = shadowCastingObjects[i]->GetY() + shadowCastingObjects[i]->GetH();
BottomLeft.Start = LightPos;
BottomLeft.End.x = shadowCastingObjects[i]->GetX();
BottomLeft.End.y = shadowCastingObjects[i]->GetY() + shadowCastingObjects[i]->GetH();
CreateShadowRay(LightPos, TopLeft);
CreateShadowRay(LightPos, TopRight);
CreateShadowRay(LightPos, BottomRight);
CreateShadowRay(LightPos, BottomLeft);
glBegin(GL_QUADS);
if(TopLeft.Start.y < LightPos.y)
{
glVertex2f(TopLeft.Start.x, TopLeft.Start.y);
glVertex2f(TopLeft.End.x, TopLeft.End.y);
glVertex2f(TopRight.End.x, TopRight.End.y);
glVertex2f(TopRight.Start.x, TopRight.Start.y);
}
if(TopRight.Start.x > LightPos.x)
{
glVertex2f(TopRight.Start.x, TopRight.Start.y);
glVertex2f(TopRight.End.x, TopRight.End.y);
glVertex2f(BottomRight.End.x, BottomRight.End.y);
glVertex2f(BottomRight.Start.x, BottomRight.Start.y);
}
if(BottomRight.Start.y > LightPos.y)
{
glVertex2f(BottomRight.Start.x, BottomRight.Start.y);
glVertex2f(BottomRight.End.x, BottomRight.End.y);
glVertex2f(BottomLeft.End.x, BottomLeft.End.y);
glVertex2f(BottomLeft.Start.x, BottomLeft.Start.y);
}
if(BottomLeft.Start.x < LightPos.x)
{
glVertex2f(BottomLeft.Start.x, BottomLeft.Start.y);
glVertex2f(BottomLeft.End.x, BottomLeft.End.y);
glVertex2f(TopLeft.End.x, TopLeft.End.y);
glVertex2f(TopLeft.Start.x, TopLeft.Start.y);
}
glEnd();
}
// Revert rendering modes.
glEnable(GL_BLEND);
glColor4f(1, 1, 1, 1);
glPopMatrix();
}
// There is a minor bug with this method, when the LightPos.x
// is equal to the RayCast.x value, the shadow is not created
// as intended. When I find a fix, I'll update this code.
// If anyone has a fix, feel free to comment below.
void CWorld::CreateShadowRay(const math::CVector2& LightPos,
math::CRay2& RayCast)
{
// Calculate slope
// m = (y2 - y1) / (x2 - x1)
float slope = RayCast.GetSlope();
// Translate the ray from its original position to
// being from the vertex to a distance
// approx. 5000px away.
RayCast.Start = RayCast.End;
if(RayCast.End.x > LightPos.x)
{
RayCast.End.x += 5000;
RayCast.End.y += 5000 * slope;
}
else if(RayCast.End.x < LightPos.x)
{
RayCast.End.x -= 5000;
RayCast.End.y -= 5000 * slope;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment