The physical basis of the colors of an oil slick is iridescence, and also related to Newton's rings. Specifically, the thickness of the oil layer is on the order of the wavelength of light. Since light reflects from both the top and bottom surface of the oil, at any given wavelength, at some angles the two reflections will be out of phase and cancel each other out; at other angles the reflections will be in phase and add together. This happens at different angles for every wavelength, so illuminating the oil with white light produces all those colors. If you illuminated it with a single frequency (e.g. laser light) you would only see a series of light and dark rings.
If you ignore refraction in the oil layer, just working out the geometry of the situation, you can find that the brightness of the reflected light for any given wavelength should vary like
sin(2.0 * pi * oilThickness / (dot(L, H) * wavelength)) * 0.5 + 0.5
Theoretically this should be integrated over all wavelengths, but in practice you can probably just do it for red, green, and blue - let's say 700, 550, and 400 nm, respectively. Changing the oil thickness will change the apparent radius of the rings of color. I would probably wrap the 2.0 * pi * oilThickness / wavelength
into a single RGB value provided to the shader as a uniform value. You could multiply it by a texture to simulate varying thickness of oil, if desired - that's probably what gives most of the interesting texture in the image above.
That produces an RGB color value that you can multiply into your BRDF. The dot(L, H)
factor would be used for point/directional lights, and you can substitute dot(N, V)
in there for applying this to an environment map reflection as well.
Disclaimer: I haven't tried this out in a shader, just drawn some diagrams and convinced myself it "should work"...so let me know the results if you do try it! :)