Index: lib/mpl_toolkits/mplot3d/axes3d.py
===================================================================
--- lib/mpl_toolkits/mplot3d/axes3d.py	(revision 8802)
+++ lib/mpl_toolkits/mplot3d/axes3d.py	(working copy)
@@ -719,21 +719,24 @@
             fcolors = self._shade_colors_lightsource(Z, cmap, lightsource)
 
         polys = []
-        normals = []
+        if cmap is None and shade:
+            totpts = int(np.ceil(float(rows - 1) / rstride) * \
+                         np.ceil(float(cols - 1) / cstride))
+            v1 = np.empty((totpts,3))
+            v2 = np.empty((totpts,3))
+            which = 0
         #colset contains the data for coloring: either average z or the facecolor
         colset = []
-        for rs in np.arange(0, rows-1, rstride):
-            for cs in np.arange(0, cols-1, cstride):
+        for rs in xrange(0, rows-1, rstride):
+            for cs in xrange(0, cols-1, cstride):  
                 ps = []
-                corners = []
                 for a, ta in [(X, tX), (Y, tY), (Z, tZ)]:
-                    ztop = a[rs][cs:min(cols, cs+cstride+1)]
-                    zleft = ta[min(cols-1, cs+cstride)][rs:min(rows, rs+rstride+1)]
-                    zbase = a[min(rows-1, rs+rstride)][cs:min(cols, cs+cstride+1):]
-                    zbase = zbase[::-1]
-                    zright = ta[cs][rs:min(rows, rs+rstride+1):]
-                    zright = zright[::-1]
-                    corners.append([ztop[0], ztop[-1], zbase[0], zbase[-1]])
+                    ztop = a[rs,cs:min(cols, cs+cstride+1)]
+                    zleft = a[rs+1:min(rows, rs+rstride+1),
+                          min(cols-1, cs+cstride)]
+                    zbase = a[min(rows-1, rs+rstride),
+                          cs:min(cols-1, cs+cstride):][::-1]
+                    zright = a[rs:min(rows-1, rs+rstride):,cs][::-1]
                     z = np.concatenate((ztop, zleft, zbase, zright))
                     ps.append(z)
 
@@ -758,10 +761,12 @@
                 # Only need vectors to shade if no cmap
                 if cmap is None and shade:
                     i1, i2, i3 = 0, int(len(ps2)/3), int(2*len(ps2)/3)
-                    v1 = np.array(ps2[i1]) - np.array(ps2[i2])
-                    v2 = np.array(ps2[i2]) - np.array(ps2[i3])
-                    normals.append(np.cross(v1, v2))
-
+                    i1, i2, i3 = 0, int(len(ps2)/3), int(2*len(ps2)/3)
+                    v1[which] = np.array(ps2[i1]) - np.array(ps2[i2])
+                    v2[which] = np.array(ps2[i2]) - np.array(ps2[i3])
+                    which += 1
+        if cmap is None and shade:
+            normals = np.cross(v1, v2)
         polyc = art3d.Poly3DCollection(polys, *args, **kwargs)
 
         if fcolors is not None:
@@ -802,18 +807,21 @@
             normals.append(np.cross(v1, v2))
         return normals
 
+    def getshades(self, normals):
+        '''
+        Find the normalized vectors of the normals and dot them with
+        the vector [-1,-1,0.5] to get the proper shadings.
+        '''
+        return np.dot(normals/np.sqrt((normals**2).sum(axis=1))[:,np.newaxis],
+               np.array([[-1],[-1],[0.5]])).squeeze()
+
     def _shade_colors(self, color, normals):
         '''
         Shade *color* using normal vectors given by *normals*.
         *color* can also be an array of the same length as *normals*.
         '''
 
-        shade = []
-        for n in normals:
-            n = n / proj3d.mod(n)
-            shade.append(np.dot(n, [-1, -1, 0.5]))
-
-        shade = np.array(shade)
+        shade = self.getshades(np.array(normals))
         mask = ~np.isnan(shade)
 
         if len(shade[mask]) > 0:
@@ -821,11 +829,10 @@
             if art3d.iscolor(color):
                 color = color.copy()
                 color[3] = 1
-                colors = [color * (0.5 + norm(v) * 0.5) for v in shade]
+                colors = np.outer(0.5 + norm(shade) * 0.5, color)
             else:
-                colors = [np.array(colorConverter.to_rgba(c)) * \
-                            (0.5 + norm(v) * 0.5) \
-                            for c, v in zip(color, shade)]
+		colors = np.array(colorConverter.to_rgba_array(color) * \
+                          (0.5 + 0.5 * norm(shade)[:,None]))
         else:
             colors = color.copy()
 
