Hello,
I just recently decided to move my 2D game to use LWJGL due to Java2D simply being sluggish and a bit ugly in quite mundane tasks. I already have a Line-of-sight algorithm for determining a visible polygon. What I want is:
The characters line of sight rendered as a clear clipped field of vision.
The rest of the map rendered in a darker shade or perhaps grayscale.
I have been trying to find a reasonable way to do this. I'm currently experiencing with Stencil buffers, but the results are indefinite. The rendering code for the field of vision works splendidly, but this solution forces me to render the map twice.
map.render();
GL11.glDisable(GL11.GL_TEXTURE_2D);
// Render gray overlay on the map
GL11.glBegin(GL11.GL_QUADS);
GL11.glColor4d(0.25, 0.25, 0.25, 0.25);
GL11.glVertex2d(m_Viewpoint.getX(), m_Viewpoint.getY());
GL11.glVertex2d(m_Viewpoint.getX()+Display.getWidth(), m_Viewpoint.getY());
GL11.glVertex2d(m_Viewpoint.getX()+Display.getWidth(), m_Viewpoint.getY()+Display.getHeight());
GL11.glVertex2d(m_Viewpoint.getX(), m_Viewpoint.getY()+Display.getHeight());
GL11.glEnd();
// Clear stencil buffer & enable
GL11.glClearStencil(0);
glClear(GL11.GL_STENCIL_BUFFER_BIT);
GL11.glEnable (GL11.GL_STENCIL_TEST);
GL11.glStencilFunc (GL11.GL_ALWAYS, 0x1, 0x1);
GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE);
GL11.glColorMask(false, false, false, false);
// Render FoV to stencil buffer
GL11.glColor4d(1, 1, 1, 1);
GL11.glBegin(GL11.GL_TRIANGLE_FAN);
GL11.glVertex2d(mPlayer.getX(), mPlayer.getY());
for(KPoint p : mPlayer.getVisionPolygon().points) {
GL11.glVertex2d(p.x, p.y);
}
GL11.glVertex2d(mPlayer.getVisionPolygon().points.get(0).x, mPlayer.getVisionPolygon().points.get(0).y);
GL11.glEnd();
GL11.glColor4d(1.0, 1.0, 1.0, 1.0);
GL11.glEnable(GL11.GL_TEXTURE_2D);
GL11.glStencilFunc (GL11.GL_EQUAL, 0x1,
GL11.glColorMask(true, true, true, true);
map.render()
objects.render()
Basically it does exactly what it's supposed and the performance is still alright, but that is partly due to the simple nature of the test scenario as well. Is there a simple, easier way to achieve the same results without having to render the map twice? I can intuitively think of some sort of alpha mask rendering (same idea as in this, but instead of using binary stencil buffer, i would have a proper alpha mask to draw under - i.e. fov as 0,0,0,0 and everything else as 25,25,25,25 [using the same colors as in above code]). The stencil buffer could then be used to clip the sprites ? In this case, however, I would be rendering my FoV to two places (and I don't even know how exactly I should be approaching such alpha mask problem). Is there an easy way to do it?
I'm a newbie here and haven't worked with OpenGL in years, so all feedback/help is welcome.