Perhaps the clue was in the original question all along - what's the problem with driving LEDs? Well, the main problem seems to be sourcing current instead of sinking it.
Admittedly, Jason was using some inline resistors on his LEDs which may have limited the current slightly on each LED, but the main problem we'd had with our 595s was that we we driving - i.e. providing positive voltage to - the LEDs through each pin of the shift register.
Different manufacturers of different shift registers give different technical specifications; but one thing that most are clear on - you can almost always sink a lot more current that you can source it (the NXP shift registers we have here also have internal clamp diodes, allowing you to sink a higher voltage than the supply voltage - but that's a whole other issue).
Now we're trying to create a circuit board on a relatively small space, and don't really want the components to be all that obtrusive (since the panel, once soldered up, is supposed to be the wall of a sci-fi interior). If we really have to, we can put inline resistors on each LED, but for testing, we left them off.
Instead of sourcing current, we joined all the anodes (long legs) of the LEDs to our 3.3v power supply. The cathodes (short legs that normally go to ground) are connected to the output pins of a couple of shift registers.
We've gone for 74HC164 shift registers, over the 595s, because these don't require a latch line; this means that the outputs change immediately as the data is shifted in, but it also means one less connector on every PCB section. Using exactly the same firmware as before, we simply cascaded the "last" output (i/o7) to the "data in" pin on the next shift register in the chain and wired up the clock and data lines to our PIC 16F1825.
Rather fortuitously, everything worked first time. Even better than that, everything worked, without current limiting resistors on the LEDs - and they all appeared to be a uniform brightness!
This was very encouraging - we've managed to lose on of the required connecting wires (no need to latch) and we've got uniform brightness, even when multiple LEDs are lit up. The only downside so far is that there's a very noticeable flicker each time the data is sent, as the shift register outputs update with every clock cycle:
Although not too obvious in the video, because of the camera frame rate, every now and again you can see a visible flicker as the LED patterns update. This is more noticeable in real life.
Fixing this flicker shouldn't be too difficult to resolve. At least, the flickering during updating can be eliminated - or at least, replaced with one, single flicker: since the LEDs are all sharing a common power supply, one solution might be to put this power rail through an NPN transistor (something like a 2N2222 perhaps?)
Just before pushing more data to refresh the display, we could turn off the transistor (starving the LEDs of their supply voltage so they go out) then push all the data into the cascaded LEDs (there may easily be twenty or thirty or more in a chain) then bring the transistor back up, illuminating all the required LEDs at the same time.
It will mean one single (possibly longer) flicker when the lights change, but - given that there could be a relatively large number of shift registers all cascading off each other - this is preferable to seeing the data flicker on each data/clock cycle on every wall section. It also means that the transistor becomes like a "latch" - but the latch line does not need to be cascaded along the entire chain of shift registers.
It's food for thought. We're hoping to get a few PCBs etched this week, so we'll be able to try out a couple of different designs, using both the LED driver and these shift registers, and compare the performance of both.