It can seem attractive to handle this kind of problem by reading back the brightness data -- after all, you're already rendering that information and so it will already be there, available, and up-to-date.
Unfortunately, it's probably not the best way to do it. Reading back data from the GPU isn't particularly fast or well-suited to this kind of operation. You are better off solving the visibility problem entirely on the CPU and basing it entirely off game data instead of graphics data.
You already know where all your lights are in the game world, and where the player is (since you're currently rendering them). A much more efficient approach to determining if the player is visible is to:
- Collect all the lights within a reasonable distance to the player (everything close enough to possibly illuminate the player). You can optimize this with some form of spatial partitioning of your game data, but if you have few enough lights per level you can also just brute-force it.
- For every light, apply the light's attenuated value to the player's total "lit" value.
- If the total "lit" value of the player exceeds some threshold, the player is visible. Otherwise the player is hidden in the shadows.
Not only will this be much more straightforward and faster than doing a read-back, it will allow you to tie in line-of-sight visibility checks if you want, as well.